├── .gitignore
├── CHANGES.md
├── LICENSE
├── README.md
├── __init__.py
├── osrsmath
├── __init__.py
├── apps
│ ├── GUI
│ │ ├── __init__.py
│ │ ├── config.py
│ │ ├── images
│ │ │ ├── logo.png
│ │ │ ├── monster
│ │ │ │ ├── Attack_icon.webp
│ │ │ │ ├── Combat_icon.webp
│ │ │ │ ├── Defence_icon.webp
│ │ │ │ ├── Hitpoints_icon.webp
│ │ │ │ ├── Magic_Damage_icon.webp
│ │ │ │ ├── Magic_icon.webp
│ │ │ │ ├── Ranged_Strength_icon.webp
│ │ │ │ ├── Ranged_icon.webp
│ │ │ │ ├── Strength_icon.webp
│ │ │ │ ├── White_dagger.webp
│ │ │ │ ├── White_scimitar.webp
│ │ │ │ ├── White_warhammer.webp
│ │ │ │ └── print_names.py
│ │ │ └── skill_icons
│ │ │ │ ├── Agility.png
│ │ │ │ ├── Attack.png
│ │ │ │ ├── Construction.png
│ │ │ │ ├── Cooking.png
│ │ │ │ ├── Crafting.png
│ │ │ │ ├── Defence.png
│ │ │ │ ├── Farming.png
│ │ │ │ ├── Firemaking.png
│ │ │ │ ├── Fishing.png
│ │ │ │ ├── Fletching.png
│ │ │ │ ├── Herblore.png
│ │ │ │ ├── Hitpoints.png
│ │ │ │ ├── Hunter.png
│ │ │ │ ├── Magic.png
│ │ │ │ ├── Mining.png
│ │ │ │ ├── Prayer.png
│ │ │ │ ├── Ranged.png
│ │ │ │ ├── Runecraft.png
│ │ │ │ ├── Slayer.png
│ │ │ │ ├── Smithing.png
│ │ │ │ ├── Strength.png
│ │ │ │ ├── Thieving.png
│ │ │ │ ├── Woodcutting.png
│ │ │ │ └── download_skill_icons.py
│ │ ├── monsters
│ │ │ ├── __init__.py
│ │ │ ├── create_player_stat.py
│ │ │ ├── monsters_skeleton.py
│ │ │ ├── monsters_skeleton.ui
│ │ │ └── player_stats.py
│ │ ├── optimize
│ │ │ ├── __init__.py
│ │ │ ├── ignore_adjust_skeleton.py
│ │ │ ├── ignore_adjust_skeleton.ui
│ │ │ ├── optimize_skeleton.py
│ │ │ ├── optimize_skeleton.ui
│ │ │ ├── player_skeleton.py
│ │ │ └── player_skeleton.ui
│ │ ├── resources.py
│ │ ├── resources.qrc
│ │ └── shared
│ │ │ ├── __init__.py
│ │ │ ├── application.py
│ │ │ ├── stylesheets
│ │ │ ├── AMOLED.qss
│ │ │ ├── Aqua.qss
│ │ │ ├── ConsoleStyle.qss
│ │ │ ├── ElegantDark.qss
│ │ │ ├── LICENSE1
│ │ │ ├── LICENSE2 (darkorange)
│ │ │ ├── License.txt
│ │ │ ├── ManjaroMix.qss
│ │ │ ├── MaterialDark.qss
│ │ │ ├── README.md
│ │ │ ├── Ubuntu.qss
│ │ │ ├── blue.css
│ │ │ ├── darkorange.css
│ │ │ ├── darkred.css
│ │ │ └── images
│ │ │ │ ├── checkbox.png
│ │ │ │ ├── convert.py
│ │ │ │ ├── down_arrow.png
│ │ │ │ └── handle.png
│ │ │ ├── util.py
│ │ │ └── widgets.py
│ ├── __init__.py
│ ├── monsters
│ │ ├── __init__.py
│ │ ├── gui_single.py
│ │ ├── gui_single.ui
│ │ ├── main.py
│ │ └── panel.py
│ ├── optimize
│ │ ├── Applications
│ │ │ ├── __init__.py
│ │ │ └── package.py
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── data
│ │ │ ├── ignore.json
│ │ │ ├── monsters.json
│ │ │ └── player.json
│ │ ├── gui_single.py
│ │ ├── gui_single.ui
│ │ ├── images
│ │ │ └── interface.png
│ │ ├── logic
│ │ │ ├── __init__.py
│ │ │ ├── evaluation.py
│ │ │ ├── gear.py
│ │ │ ├── optimize.py
│ │ │ └── utility.py
│ │ └── panels
│ │ │ ├── __init__.py
│ │ │ ├── ignore_adjust.py
│ │ │ ├── optimize.py
│ │ │ └── player.py
│ └── path
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── path.py
│ │ ├── printers.py
│ │ ├── tree.pdf
│ │ └── tree_1def.pdf
├── config.py
├── docs
│ ├── .ipynb_checkpoints
│ │ ├── SolvingOSRS-checkpoint.ipynb
│ │ └── Untitled-checkpoint.ipynb
│ ├── SolvingOSRS.ipynb
│ └── latex
│ │ ├── .ipynb_checkpoints
│ │ └── main-checkpoint.pdf
│ │ ├── img
│ │ ├── Older
│ │ │ ├── Details.png
│ │ │ ├── Equipment.png
│ │ │ ├── NMZ.png
│ │ │ ├── Stats.png
│ │ │ ├── fig_time.pdf
│ │ │ ├── levels_recur.pdf
│ │ │ ├── levels_recur_10_10.pdf
│ │ │ ├── levels_recur_60_90.pdf
│ │ │ └── training_scheme.pdf
│ │ ├── combat
│ │ │ ├── Combat_triangle.png
│ │ │ ├── Equipment_Stats_interface_and_triangle.png
│ │ │ ├── bandos.png
│ │ │ ├── bandos_one_shot.png
│ │ │ ├── bandos_slim.png
│ │ │ ├── damage_distributions.png
│ │ │ ├── defence_training.png
│ │ │ ├── fight_outcome_probabilities.png
│ │ │ ├── gear_optimizer.png
│ │ │ ├── training_graph.png
│ │ │ ├── training_order60.png
│ │ │ └── training_order_sequence.png
│ │ ├── firemaking
│ │ │ └── wintertodt_actions.png
│ │ ├── general
│ │ │ ├── skill_capes
│ │ │ │ ├── Firemaking_cape_detail.png
│ │ │ │ ├── Howling_Snow_Storm-0.png
│ │ │ │ ├── Howling_Snow_Storm-0.xcf
│ │ │ │ ├── Howling_Snow_Storm.gif
│ │ │ │ └── transparent_Howling_Snow_Storm-0.png
│ │ │ ├── skills
│ │ │ │ ├── Construction_icon.png
│ │ │ │ ├── Farming_icon.png
│ │ │ │ ├── Firemaking_icon.png
│ │ │ │ ├── Fletching_icon.png
│ │ │ │ ├── Herblore_icon.png
│ │ │ │ ├── Woodcutting_icon.png
│ │ │ │ └── blank.png
│ │ │ ├── skills_quest_player.png
│ │ │ └── wildmudkip_maxing.png
│ │ ├── mining
│ │ │ ├── optimal_order.pdf
│ │ │ └── varying_paydirt.100.png
│ │ ├── quests
│ │ │ ├── osrs_by_requirement.pdf
│ │ │ ├── universe.png
│ │ │ └── zoom.png
│ │ └── woodcutting
│ │ │ └── experience.pdf
│ │ ├── main.bbl
│ │ ├── main.bib
│ │ ├── main.blg
│ │ ├── main.out
│ │ ├── main.pdf
│ │ ├── main.tex
│ │ ├── main.toc
│ │ ├── mystyle.sty
│ │ └── tex
│ │ ├── chunks
│ │ ├── ChunkSolver.md
│ │ ├── ChunkSolver.pdf
│ │ ├── image-2.png
│ │ └── image.png
│ │ ├── combat
│ │ ├── appendix
│ │ │ ├── power_reduction.tex
│ │ │ └── recursive_approximation.tex
│ │ ├── list_of_terms.tex
│ │ ├── markov_chain.tex
│ │ ├── models.tex
│ │ ├── optimal_training_order.tex
│ │ ├── optimizing_player_equipment.tex
│ │ └── overview.tex
│ │ ├── firemaking
│ │ └── wintertodt.tex
│ │ ├── general
│ │ └── experience_and_levels.tex
│ │ ├── introduction.tex
│ │ ├── mining
│ │ └── mining.tex
│ │ ├── quests
│ │ └── quests.tex
│ │ ├── title.pdf
│ │ ├── title.tex
│ │ └── woodcutting
│ │ └── woodcutting.tex
├── examples
│ ├── chunk
│ │ ├── .ipynb_checkpoints
│ │ │ └── ChunkSolver-checkpoint.ipynb
│ │ └── ChunkSolver.ipynb
│ ├── combat
│ │ ├── DamageDistributions
│ │ │ └── damage_distributions.py
│ │ └── old
│ │ │ ├── part_I
│ │ │ ├── Accuracy.pdf
│ │ │ └── accuracy.py
│ │ │ ├── part_II
│ │ │ ├── average_damage.pdf
│ │ │ ├── average_damage.py
│ │ │ ├── best_model.pdf
│ │ │ ├── best_model.py
│ │ │ ├── colors.py
│ │ │ ├── comparison.py
│ │ │ ├── errors.pdf
│ │ │ ├── errors.png
│ │ │ ├── generate_simulation.py
│ │ │ ├── models
│ │ │ │ ├── Average.png
│ │ │ │ ├── Crude.png
│ │ │ │ ├── MarkovChain.png
│ │ │ │ ├── MarkovChainApproximation.png
│ │ │ │ ├── Recursive.png
│ │ │ │ ├── RecursiveApproximation.png
│ │ │ │ └── generate.py
│ │ │ ├── turns_to_kill.pdf
│ │ │ ├── turns_to_kill.py
│ │ │ └── turns_to_kill_zoom.pdf
│ │ │ └── part_III
│ │ │ ├── big_tree.pdf
│ │ │ ├── optimize
│ │ │ ├── backup.pdf
│ │ │ ├── best_gear_example.py
│ │ │ ├── costs.py
│ │ │ ├── gold_efficiency.pdf
│ │ │ ├── settings.json
│ │ │ ├── weapon_comparison.pdf
│ │ │ └── weapon_comparison.py
│ │ │ ├── recur_(1, 1, 1).pdf
│ │ │ ├── tree.pdf
│ │ │ └── tree_bz_dagger_vs_dscim.pdf
│ ├── firemaking
│ │ ├── policies.pdf
│ │ ├── profit.pdf
│ │ ├── summary.out
│ │ ├── summary.pdf
│ │ ├── summary.tex
│ │ └── wintertodt.py
│ ├── mining
│ │ ├── Prospector_boots_detail.pdf
│ │ ├── Prospector_helmet_detail.pdf
│ │ ├── Prospector_jacket_detail.pdf
│ │ ├── Prospector_legs_detail.pdf
│ │ ├── optimal_order.pdf
│ │ ├── optimal_prospector_order.py
│ │ ├── sorted.pdf
│ │ ├── sorted.py
│ │ ├── varying_paydirt.100.pdf
│ │ ├── varying_paydirt.100.png
│ │ ├── varying_paydirt.1000.pdf
│ │ ├── varying_paydirt.1000.png
│ │ ├── varying_paydirt.10000.pdf
│ │ ├── varying_paydirt.10000.png
│ │ └── varying_paydirt.py
│ ├── quests
│ │ ├── model
│ │ │ ├── README.md
│ │ │ ├── lib
│ │ │ │ ├── bindings
│ │ │ │ │ └── utils.js
│ │ │ │ ├── tom-select
│ │ │ │ │ ├── tom-select.complete.min.js
│ │ │ │ │ └── tom-select.css
│ │ │ │ └── vis-9.1.2
│ │ │ │ │ ├── vis-network.css
│ │ │ │ │ └── vis-network.min.js
│ │ │ ├── osrs_wiki_quest_parser.py
│ │ │ ├── output
│ │ │ │ ├── map.html
│ │ │ │ ├── map.png
│ │ │ │ ├── osrs
│ │ │ │ │ ├── osrs_by_quest.pdf
│ │ │ │ │ ├── osrs_by_requirement.pdf
│ │ │ │ │ └── osrs_quest_viewer.html
│ │ │ │ └── rs3
│ │ │ │ │ ├── rs3_by_quest.pdf
│ │ │ │ │ ├── rs3_by_requirement.pdf
│ │ │ │ │ └── rs3_quest_viewer.html
│ │ │ ├── parser_files
│ │ │ │ ├── osrs_quest_data.json
│ │ │ │ └── rs3_quest_data.json
│ │ │ ├── quest.py
│ │ │ ├── quest_view.js
│ │ │ ├── quest_view.py
│ │ │ └── rs3_wiki_quest_parser.py
│ │ └── solver
│ │ │ ├── get_quest_cape.ods
│ │ │ └── quest_solver.py
│ └── woodcutting
│ │ ├── experience.pdf
│ │ └── optimal_trees.py
├── general
│ ├── __init__.py
│ ├── constants.py
│ ├── player.py
│ └── skills.py
├── skills
│ ├── combat
│ │ ├── IndividualSolutions
│ │ │ └── gauntlet
│ │ │ │ └── SimpleGame
│ │ │ │ ├── .ipynb_checkpoints
│ │ │ │ └── SimpleGauntletSolution-checkpoint.ipynb
│ │ │ │ └── SimpleGauntletSolution.ipynb
│ │ ├── __init__.py
│ │ ├── accuracy.py
│ │ ├── damage.py
│ │ ├── data
│ │ │ ├── items-2h.json
│ │ │ ├── items-None.json
│ │ │ ├── items-ammo.json
│ │ │ ├── items-body.json
│ │ │ ├── items-cape.json
│ │ │ ├── items-feet.json
│ │ │ ├── items-hands.json
│ │ │ ├── items-head.json
│ │ │ ├── items-legs.json
│ │ │ ├── items-neck.json
│ │ │ ├── items-ring.json
│ │ │ ├── items-shield.json
│ │ │ ├── items-weapon.json
│ │ │ ├── monsters-complete.json
│ │ │ ├── simulations
│ │ │ │ ├── simulation.10.dat
│ │ │ │ ├── simulation.1000.5.dat
│ │ │ │ ├── simulation.10000.5.dat
│ │ │ │ ├── simulation.10000.dat
│ │ │ │ ├── simulation.100000.dat
│ │ │ │ └── simulation.1000000.dat
│ │ │ └── weapon_info.dat
│ │ ├── decisions
│ │ │ └── gamestate.py
│ │ ├── defence.py
│ │ ├── distributions.py
│ │ ├── fighter.py
│ │ ├── items.py
│ │ ├── monsters.py
│ │ └── spells.py
│ ├── firemaking
│ │ └── wintertodt.py
│ ├── mining
│ │ ├── __init__.py
│ │ └── motherload_mine.py
│ └── woodcutting
│ │ ├── Data.xlsx
│ │ ├── __init__.py
│ │ ├── entities.py
│ │ └── rates.py
└── tests
│ ├── __init__.py
│ ├── combat
│ ├── test_dps.py
│ └── test_requirements.py
│ ├── firemaking
│ └── test_firemaking.py
│ └── general
│ └── test_skills.py
├── requirements.txt
└── setup.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Distribution Files
2 | build
3 | dist
4 | osrsmath.egg-info
5 | */Applications
6 | !*/Applications/package.py
7 |
8 |
9 | # Python Output
10 | *.pyc
11 |
12 | # Latex Output
13 | *.aux
14 | *.log
15 |
--------------------------------------------------------------------------------
/CHANGES.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | ## 0.0.3.3
4 | ### Changed
5 | - Fixed some file path issues
6 |
7 | ## 0.0.3.2
8 | ### Changed
9 | - Moved 'osrsmath.model' to 'osrsmath.combat'
10 | - Moved 'osrsmath.model.general' to 'osrsmath.general'
11 |
12 | ### Added
13 | - Added an `__init__.py` file that was required for PyPi to work.
14 |
15 | ## 0.0.3
16 | ### Changed
17 | - Hotfix: Corrected the Obsidian armour accuracy boost to be 1.1x instead of 1.3x.
18 | - Hotfix: Corrected the Berserker necklace accuracy boost to be 1.0x instead of 1.2x.
19 |
20 | ## 0.0.2
21 | ### Added
22 | - Optimize app was added.
23 |
24 | ### Removed
25 | - Temporarily removed support for the Path app since it was out of date.
26 |
27 |
28 | ## 0.0.1
29 | - First release
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Nawar Ismail
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
1 | from osrsmath.config import TOP
2 | from pathlib import Path
3 | __doc__ = open(Path(TOP)/'../README.md').read()
--------------------------------------------------------------------------------
/osrsmath/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/__init__.py
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/__init__.py
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/config.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | images_directory = os.path.join(os.path.dirname(__file__), 'images')
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/logo.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/monster/Attack_icon.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/monster/Attack_icon.webp
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/monster/Combat_icon.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/monster/Combat_icon.webp
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/monster/Defence_icon.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/monster/Defence_icon.webp
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/monster/Hitpoints_icon.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/monster/Hitpoints_icon.webp
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/monster/Magic_Damage_icon.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/monster/Magic_Damage_icon.webp
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/monster/Magic_icon.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/monster/Magic_icon.webp
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/monster/Ranged_Strength_icon.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/monster/Ranged_Strength_icon.webp
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/monster/Ranged_icon.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/monster/Ranged_icon.webp
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/monster/Strength_icon.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/monster/Strength_icon.webp
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/monster/White_dagger.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/monster/White_dagger.webp
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/monster/White_scimitar.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/monster/White_scimitar.webp
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/monster/White_warhammer.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/monster/White_warhammer.webp
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/monster/print_names.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | for path in Path('.').rglob('*.webp'):
3 | path = str(path).replace('.webp', '')
4 | print(f'images/skill_icons/{path}.webp')
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Agility.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Agility.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Attack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Attack.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Construction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Construction.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Cooking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Cooking.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Crafting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Crafting.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Defence.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Defence.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Farming.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Farming.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Firemaking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Firemaking.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Fishing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Fishing.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Fletching.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Fletching.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Herblore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Herblore.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Hitpoints.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Hitpoints.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Hunter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Hunter.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Magic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Magic.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Mining.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Mining.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Prayer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Prayer.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Ranged.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Ranged.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Runecraft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Runecraft.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Slayer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Slayer.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Smithing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Smithing.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Strength.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Strength.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Thieving.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Thieving.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/Woodcutting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/images/skill_icons/Woodcutting.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/images/skill_icons/download_skill_icons.py:
--------------------------------------------------------------------------------
1 | from osrsmath.general.skills import get_skills
2 | import requests
3 | from pprint import pprint
4 |
5 | def download(url, filename):
6 | r = requests.get(url)
7 | with open(filename, 'wb') as f:
8 | f.write(r.content)
9 |
10 | def parse_html_link(html):
11 | start_of_line_with_link = '
File usage
images/skill_icons/{skill}.png')
32 | #print(f'Downloading {skill} Icon... ({i}/{len(skills)} - {100*i/len(skills):.1f}%)')
33 | #download_skill_icon(skill)
34 |
35 |
36 |
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/monsters/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/monsters/__init__.py
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/monsters/create_player_stat.py:
--------------------------------------------------------------------------------
1 | ''' This is a one-time file to create the base xml for the player stats widget. '''
2 |
3 | if __name__ == '__main__':
4 | basic = lambda r, c, skill: f"""\
5 | -
6 |
7 |
8 |
9 |
10 |
11 | ../images/skill_icons/{skill.capitalize()}.png
12 |
13 |
14 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 | """
23 |
24 | skills = [
25 | ['attack', 'hitpoints', 'mining'],
26 | ['strength', 'agility', 'smithing'],
27 | ['defence', 'herblore', 'fishing'],
28 | ['ranged', 'thieving', 'cooking'],
29 | ['prayer', 'crafting', 'firemaking'],
30 | ['magic', 'fletching', 'woodcutting'],
31 | ['runecraft', 'slayer', 'farming'],
32 | ['construction', 'hunter'],
33 | ]
34 |
35 |
36 | new_text = []
37 | starting = ''
38 | ending = ''
39 | reading = False
40 | for line in open('player_stats.ui'):
41 | if (not reading) and (line.strip() == starting):
42 | reading = True
43 | new_text.append(line)
44 | for i in range(len(skills)):
45 | for j, skill in enumerate(skills[i]):
46 | new_text.append(basic(i, j, skills[i][j]))
47 |
48 | if line.strip() == ending:
49 | reading = False
50 |
51 |
52 |
53 | if not reading:
54 | new_text.append(line)
55 |
56 | with open('test.ui', 'w') as f:
57 | f.writelines(new_text)
58 |
59 |
60 |
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/monsters/player_stats.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'player_stats.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.14.1
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 |
10 |
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/optimize/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/optimize/__init__.py
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/optimize/ignore_adjust_skeleton.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | ################################################################################
4 | ## Form generated from reading UI file 'ignore_adjust_skeleton.ui'
5 | ##
6 | ## Created by: Qt User Interface Compiler version 5.15.0
7 | ##
8 | ## WARNING! All changes made in this file will be lost when recompiling UI file!
9 | ################################################################################
10 |
11 | from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject,
12 | QObject, QPoint, QRect, QSize, QTime, QUrl, Qt)
13 | from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
14 | QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter,
15 | QPixmap, QRadialGradient)
16 | from PySide6.QtWidgets import *
17 |
18 |
19 | class Ui_IgnoreAdjustPanel(object):
20 | def setupUi(self, IgnoreAdjustPanel):
21 | if not IgnoreAdjustPanel.objectName():
22 | IgnoreAdjustPanel.setObjectName(u"IgnoreAdjustPanel")
23 | IgnoreAdjustPanel.resize(267, 254)
24 | IgnoreAdjustPanel.setMinimumSize(QSize(267, 0))
25 | IgnoreAdjustPanel.setMaximumSize(QSize(267, 16777215))
26 | self.gridLayout = QGridLayout(IgnoreAdjustPanel)
27 | self.gridLayout.setObjectName(u"gridLayout")
28 | self.ignore = QRadioButton(IgnoreAdjustPanel)
29 | self.ignore.setObjectName(u"ignore")
30 | self.ignore.setChecked(True)
31 |
32 | self.gridLayout.addWidget(self.ignore, 0, 0, 1, 1)
33 |
34 | self.adjustments = QRadioButton(IgnoreAdjustPanel)
35 | self.adjustments.setObjectName(u"adjustments")
36 |
37 | self.gridLayout.addWidget(self.adjustments, 0, 1, 1, 1)
38 |
39 | self.text = QPlainTextEdit(IgnoreAdjustPanel)
40 | self.text.setObjectName(u"text")
41 |
42 | self.gridLayout.addWidget(self.text, 1, 0, 1, 2)
43 |
44 |
45 | self.retranslateUi(IgnoreAdjustPanel)
46 |
47 | QMetaObject.connectSlotsByName(IgnoreAdjustPanel)
48 | # setupUi
49 |
50 | def retranslateUi(self, IgnoreAdjustPanel):
51 | IgnoreAdjustPanel.setWindowTitle(QCoreApplication.translate("IgnoreAdjustPanel", u"Form", None))
52 | self.ignore.setText(QCoreApplication.translate("IgnoreAdjustPanel", u"Ignore", None))
53 | self.adjustments.setText(QCoreApplication.translate("IgnoreAdjustPanel", u"Adjustments", None))
54 | # retranslateUi
55 |
56 |
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/optimize/ignore_adjust_skeleton.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | IgnoreAdjustPanel
4 |
5 |
6 |
7 | 0
8 | 0
9 | 267
10 | 254
11 |
12 |
13 |
14 |
15 | 267
16 | 0
17 |
18 |
19 |
20 |
21 | 267
22 | 16777215
23 |
24 |
25 |
26 | Form
27 |
28 |
29 | -
30 |
31 |
32 | Ignore
33 |
34 |
35 | true
36 |
37 |
38 |
39 | -
40 |
41 |
42 | Adjustments
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | images/logo.png
4 |
5 |
6 | images/monster/Attack_icon.webp
7 | images/monster/Combat_icon.webp
8 | images/monster/Defence_icon.webp
9 | images/monster/Hitpoints_icon.webp
10 | images/monster/Magic_Damage_icon.webp
11 | images/monster/Magic_icon.webp
12 | images/monster/Ranged_icon.webp
13 | images/monster/Ranged_Strength_icon.webp
14 | images/monster/Strength_icon.webp
15 | images/monster/White_dagger.webp
16 | images/monster/White_scimitar.webp
17 | images/monster/White_warhammer.webp
18 |
19 |
20 | images/skill_icons/Attack.png
21 | images/skill_icons/Defence.png
22 | images/skill_icons/Strength.png
23 | images/skill_icons/Hitpoints.png
24 | images/skill_icons/Ranged.png
25 | images/skill_icons/Prayer.png
26 | images/skill_icons/Magic.png
27 | images/skill_icons/Cooking.png
28 | images/skill_icons/Woodcutting.png
29 | images/skill_icons/Fletching.png
30 | images/skill_icons/Fishing.png
31 | images/skill_icons/Firemaking.png
32 | images/skill_icons/Crafting.png
33 | images/skill_icons/Smithing.png
34 | images/skill_icons/Mining.png
35 | images/skill_icons/Herblore.png
36 | images/skill_icons/Agility.png
37 | images/skill_icons/Thieving.png
38 | images/skill_icons/Slayer.png
39 | images/skill_icons/Farming.png
40 | images/skill_icons/Runecraft.png
41 | images/skill_icons/Hunter.png
42 | images/skill_icons/Construction.png
43 |
44 |
45 | shared/stylesheets/images/checkbox.png
46 | shared/stylesheets/images/down_arrow.png
47 | shared/stylesheets/images/handle.png
48 |
49 |
50 |
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/shared/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/shared/__init__.py
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/shared/application.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtCore, QtGui, QtWidgets
2 | from pathlib import Path
3 |
4 | import osrsmath.config as config
5 | import sys
6 | import os
7 |
8 | def run(main_gui_class):
9 | # https://leomoon.com/journal/python/high-dpi-scaling-in-pyqt5/
10 | QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) #enable highdpi scaling
11 | QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) #use highdpi icons
12 |
13 | app = QtWidgets.QApplication(sys.argv)
14 |
15 | # START APPLICATION
16 | MainWindow = QtWidgets.QMainWindow()
17 | ui = main_gui_class()
18 | ui.MainWindow = MainWindow # Allow class to set internals
19 | ui.setupUi(MainWindow)
20 | if hasattr(ui, 'save_defaults'):
21 | MainWindow.closeEvent = lambda self: ui.save_defaults()
22 | MainWindow.show()
23 |
24 | app.setStyle('Fusion')
25 | stylesheet_file = config.resource_path(Path("apps/GUI/shared/stylesheets/darkorange.css"))
26 | with open(stylesheet_file) as f:
27 | MainWindow.setStyleSheet(f.read())
28 |
29 | # APPLICATION EXIT
30 | try:
31 | ret = app.exec_()
32 | except: # This doesn't catch a lot of things, since often abort is called
33 | if hasattr(ui, 'save_defaults'):
34 | ui.save_defaults()
35 | raise
36 | sys.exit(ret)
37 |
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/shared/stylesheets/LICENSE1:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Jaime Quiroga
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/shared/stylesheets/License.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) DevSec Studio. All rights reserved.
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/shared/stylesheets/README.md:
--------------------------------------------------------------------------------
1 | ### QT StyleSheet templates ###
2 | Themes available:
3 | 1. [Ubuntu](https://github.com/GTRONICK/QSS/blob/master/Ubuntu.qss)
4 |
5 | 
6 |
7 | 2. [ElegantDark](https://github.com/GTRONICK/QSS/blob/master/ElegantDark.qss)
8 |
9 | 
10 |
11 | 3. [MaterialDark](https://github.com/GTRONICK/QSS/blob/master/MaterialDark.qss)
12 |
13 | 
14 |
15 | 4. [ConsoleStyle](https://github.com/GTRONICK/QSS/blob/master/ConsoleStyle.qss)
16 |
17 | 
18 |
19 | 5. [AMOLED](https://github.com/GTRONICK/QSS/blob/master/AMOLED.qss)
20 |
21 | 
22 |
23 | 6. [Aqua](https://github.com/GTRONICK/QSS/blob/master/Aqua.qss)
24 |
25 | 
26 |
27 | ## The ManjaroMix Theme!: Includes a radial gradient for Checkboxes, and minimalist arrows for scrollbars. ##
28 | 7. [ManjaroMix](https://github.com/GTRONICK/QSS/blob/master/ManjaroMix.qss)
29 |
30 | 
31 |
32 | Stay tunned!, this files are being updated frequently.
33 |
34 | *Consider donating :)* **PayPal Account:** gtronick@gmail.com
35 |
36 |
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/shared/stylesheets/blue.css:
--------------------------------------------------------------------------------
1 | /*Copyright (c) DevSec Studio. All rights reserved.
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | */
22 |
23 | /*-----QWidget-----*/
24 | QWidget
25 | {
26 | background-color: #6692d3;
27 | color: #ffffff;
28 | border-color: #181c21;
29 |
30 | }
31 |
32 |
33 | /*-----QMenuBar-----*/
34 | QMenuBar
35 | {
36 | background-color: #6692fc;
37 | color: #fff;
38 | border-color: #181c21;
39 |
40 | }
41 |
42 |
43 | QMenuBar::item
44 | {
45 | background-color: transparent;
46 |
47 | }
48 |
49 |
50 | QMenuBar::item:selected
51 | {
52 | background-color: #389bff;
53 |
54 | }
55 |
56 |
57 | QMenuBar::item:pressed
58 | {
59 | background-color: #3a76b4;
60 | border: 1px solid #5ab8a0;
61 | margin-bottom: -1px;
62 | padding-bottom: 1px;
63 |
64 | }
65 |
66 |
67 | /*-----QMenu-----*/
68 | QMenu
69 | {
70 | background-color: #e1f4ff;
71 | border: 1px solid;
72 | color: #000;
73 |
74 | }
75 |
76 |
77 | QMenu::separator
78 | {
79 | height: 1px;
80 | background-color: #000;
81 | color: #ffffff;
82 | padding-left: 4px;
83 | margin-left: 10px;
84 | margin-right: 5px;
85 |
86 | }
87 |
88 |
89 | QMenu::item
90 | {
91 | min-width : 150px;
92 | padding: 3px 20px 3px 20px;
93 |
94 | }
95 |
96 |
97 | QMenu::item:selected
98 | {
99 | background-color: #3a76b4;
100 | color: #ffffff;
101 |
102 | }
103 |
104 |
105 | QMenu::item:disabled
106 | {
107 | color: #262626;
108 |
109 | }
110 |
111 |
112 | /*-----QPushButton-----*/
113 | QPushButton
114 | {
115 | background-color: #e1f4ff;
116 | color: #000000;
117 | border-style: solid;
118 | border-color: #181c21;
119 | font-weight: bold;
120 | font-size: 12px;
121 | font-family: Arial;
122 |
123 | }
124 |
125 |
126 | QPushButton::hover
127 | {
128 | background-color: #f6fbff;
129 |
130 | }
131 |
132 |
133 | QPushButton::pressed
134 | {
135 | background-color: #cdcdcd;
136 |
137 | }
138 |
139 |
140 | /*-----QLineEdit-----*/
141 | QLineEdit
142 | {
143 | background-color: #12160c;
144 | color: #ffffff;
145 | border: 1px solid #6692fc;
146 | padding: 3px;
147 |
148 | }
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/shared/stylesheets/images/checkbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/shared/stylesheets/images/checkbox.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/shared/stylesheets/images/convert.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 |
4 | def command(name):
5 | # os.system(f"convert {name} -alpha copy -fx '#000' {name}")
6 | # os.system(f"convert {name} -colorspace srgb -type truecolor {name}")
7 | os.system(f"convert {name} -set colorspace RGB -colorspace gray {name}")
8 | command('checkbox.png')
9 | command('down_arrow.png')
10 | command('handle.png')
11 |
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/shared/stylesheets/images/down_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/shared/stylesheets/images/down_arrow.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/shared/stylesheets/images/handle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/GUI/shared/stylesheets/images/handle.png
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/shared/util.py:
--------------------------------------------------------------------------------
1 | """ Contains several useful utility functions for handling the GUI.
2 | This module can be run to provide some functionality:
3 | Run: `python util.py make` to compile ALL .ui files into the respective .py files."""
4 | import os
5 | from pathlib import Path
6 |
7 | UI_COMPILER = 'pyside2-uic' # 'pyuic5'
8 | RC_COMPILER = 'pyside2-rcc' # 'pyrcc5'
9 |
10 | def make_ui(file_path):
11 | os.system(f"{UI_COMPILER} {file_path}.ui -o {file_path}.py")
12 |
13 | def make_rc(file_path):
14 | os.system(f'{RC_COMPILER} {file_path}.qrc -o {file_path}.py')
15 |
16 | def make_all(top_level_dir):
17 | for path in Path(top_level_dir).rglob('*.qrc'):
18 | print(f"Compiling QRC: {path}")
19 | extensionless_path = '/'.join(path.parts).rstrip(path.suffix)
20 | make_rc(extensionless_path)
21 |
22 | for path in Path(top_level_dir).rglob('*.ui'):
23 | print(f"Compiling UI: {path}")
24 | extensionless_path = '/'.join(path.parts).rstrip(path.suffix)
25 | make_ui(extensionless_path)
26 |
27 | if __name__ == '__main__':
28 | import sys
29 | import osrsmath.config as config
30 | if len(sys.argv) == 2 and sys.argv[1] == 'make':
31 | make_all(os.path.join(config.TOP, 'apps'))
32 |
--------------------------------------------------------------------------------
/osrsmath/apps/GUI/shared/widgets.py:
--------------------------------------------------------------------------------
1 | import collections
2 | import json
3 |
4 | class Savable:
5 | """ Handles the loading and saving of state.
6 | The Panel class should subclass this, and construct a dictionary 'entities'
7 | filled with calls to Savable.Entity. """
8 | @staticmethod
9 | def Entity(obj, default, setter, getter):
10 | return collections.namedtuple('Entity', ['object', 'default', 'set', 'get'])(
11 | obj, default, lambda v: setter(obj, v), lambda: getter(obj)
12 | )
13 |
14 | @staticmethod
15 | def DropDown(obj, default):
16 | return Savable.Entity(obj, default, lambda o, v: o.setCurrentText(v), lambda o: o.currentText())
17 |
18 | @staticmethod
19 | def LineEdit(obj, default):
20 | return Savable.Entity(obj, default, lambda o, v: o.setText(v), lambda o: o.text())
21 |
22 | @staticmethod
23 | def CheckBox(obj, default):
24 | return Savable.Entity(obj, default, lambda o, v: o.setChecked(v), lambda o: o.isChecked())
25 |
26 | def import_defaults(self, file_name):
27 | self.state = {}
28 | try:
29 | self.state = json.load(open(file_name))
30 | for name, value in self.state.items():
31 | self.entities[name].set(value)
32 | except Exception as e:
33 | print(f'Unable to import_defaults for {file_name}: {e}')
34 | pass
35 |
36 | def export_defaults(self, file_name):
37 | for name, entity in self.entities.items():
38 | self.state[name] = entity.get()
39 | json.dump(self.state, open(file_name, 'w'), indent=4)
40 |
--------------------------------------------------------------------------------
/osrsmath/apps/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/__init__.py
--------------------------------------------------------------------------------
/osrsmath/apps/monsters/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/monsters/__init__.py
--------------------------------------------------------------------------------
/osrsmath/apps/monsters/gui_single.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | ################################################################################
4 | ## Form generated from reading UI file 'gui_single.ui'
5 | ##
6 | ## Created by: Qt User Interface Compiler version 5.15.0
7 | ##
8 | ## WARNING! All changes made in this file will be lost when recompiling UI file!
9 | ################################################################################
10 |
11 | from PySide2.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject,
12 | QObject, QPoint, QRect, QSize, QTime, QUrl, Qt)
13 | from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
14 | QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter,
15 | QPixmap, QRadialGradient)
16 | from PySide2.QtWidgets import *
17 |
18 | from osrsmath.apps.monsters.panel import MonsterPanel
19 |
20 |
21 | class Ui_MainWindow(object):
22 | def setupUi(self, MainWindow):
23 | if not MainWindow.objectName():
24 | MainWindow.setObjectName(u"MainWindow")
25 | MainWindow.resize(800, 600)
26 | self.centralwidget = QWidget(MainWindow)
27 | self.centralwidget.setObjectName(u"centralwidget")
28 | self.gridLayout = QGridLayout(self.centralwidget)
29 | self.gridLayout.setObjectName(u"gridLayout")
30 | self.widget = MonsterPanel(self.centralwidget)
31 | self.widget.setObjectName(u"widget")
32 |
33 | self.gridLayout.addWidget(self.widget, 0, 0, 1, 1)
34 |
35 | MainWindow.setCentralWidget(self.centralwidget)
36 | self.menubar = QMenuBar(MainWindow)
37 | self.menubar.setObjectName(u"menubar")
38 | self.menubar.setGeometry(QRect(0, 0, 800, 21))
39 | MainWindow.setMenuBar(self.menubar)
40 | self.statusbar = QStatusBar(MainWindow)
41 | self.statusbar.setObjectName(u"statusbar")
42 | MainWindow.setStatusBar(self.statusbar)
43 |
44 | self.retranslateUi(MainWindow)
45 |
46 | QMetaObject.connectSlotsByName(MainWindow)
47 | # setupUi
48 |
49 | def retranslateUi(self, MainWindow):
50 | MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
51 | # retranslateUi
52 |
53 |
--------------------------------------------------------------------------------
/osrsmath/apps/monsters/gui_single.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 800
10 | 600
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 |
23 |
33 |
34 |
35 |
36 |
37 | MonsterPanel
38 | QWidget
39 | osrsmath/apps/monsters/panel
40 | 1
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/osrsmath/apps/monsters/main.py:
--------------------------------------------------------------------------------
1 | from osrsmath.apps.monsters.gui_single import Ui_MainWindow
2 |
3 | if __name__ == "__main__":
4 | from osrsmath.apps.GUI.shared.application import run
5 | run(Ui_MainWindow)
6 |
--------------------------------------------------------------------------------
/osrsmath/apps/optimize/Applications/__init__.py:
--------------------------------------------------------------------------------
1 | # Prevent pdoc from trying to gen documentation for Application builds.
2 |
3 | #import osrsmath.apps.optimize.Applications as app
4 | #import inspect
5 | #rint(inspect.getmembers(app, inspect.ismodule))
6 |
7 | import glob
8 |
9 | __pdoc__ = {}
10 | for f in glob.glob('**', recursive=True):
11 | print(f)
12 | # if any(f.endswith(str(i)) for i in range(0, 10)):
13 | # print('---')
14 | __pdoc__[f.replace('/', '.')] = False
15 |
16 | #__pdoc__ = {
17 | # 'osrsmath.apps.optimize.Applications': False,
18 | #}
19 |
--------------------------------------------------------------------------------
/osrsmath/apps/optimize/Applications/package.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | import PyInstaller
3 | import os
4 | import json
5 | import osrsmath.config as config
6 |
7 | import platform
8 | import shutil
9 | import sys
10 | top = system = platform.system()
11 |
12 | def compile():
13 | try:
14 | shutil.rmtree(top)
15 | except FileNotFoundError:
16 | pass
17 | os.makedirs(top)
18 |
19 | try:
20 | os.chdir(top)
21 | original_data_path = Path(config.TOP)
22 | new_data_path = Path('DATA/')
23 | additional_data = [
24 | 'combat/data/',
25 | 'apps/GUI/shared/stylesheets',
26 | 'apps/optimize/data',
27 | ]
28 |
29 | args = [
30 | '../../main.py',
31 | '--hiddenimport=pkg_resources.py2_warn',
32 | # '--onefile',
33 | *[f"--add-data {original_data_path/path}{os.pathsep}{new_data_path/path}" for path in additional_data]
34 | ]
35 | command = f'''{sys.executable} -m PyInstaller {json.dumps(args).replace('"', '').replace(',', '')[1:-1]}'''
36 | print(command)
37 | os.system(command)
38 |
39 | if system in ['Linux', 'Darwin']:
40 | # Create shortcut, I could not get symlinks to work.
41 | # This wont work if they don't execute from the top directory.
42 | with open('osrsmath-optimize', 'w') as f:
43 | f.write('#!/bin/sh\n')
44 | f.write('cd "$(dirname $0)/dist/main && ./main')
45 | os.system('chmod +x osrsmath-optimize')
46 | elif system == 'Windows':
47 | os.system(R'mklink "osrsmath-optimize" "dist\main\main.exe"')
48 |
49 |
50 |
51 | except Exception as e:
52 | print(e)
53 | finally:
54 | os.chdir('../')
55 |
56 | def run():
57 | # print(os.path.abspath('.'))
58 | os.system(f'./{top}/dist/main/main')
59 |
60 | if __name__ == '__main__':
61 | compile()
62 | run()
--------------------------------------------------------------------------------
/osrsmath/apps/optimize/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/optimize/__init__.py
--------------------------------------------------------------------------------
/osrsmath/apps/optimize/data/ignore.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignore_data": "USER IGNORES\n\n\nDEFAULT IGNORES\n# Unobtainable Items\nSpear\nStarter sword\n\n# Barbarian Assault\nBarbed arrow\nBlunt arrow\nField arrow\nBullet arrow\n\n# Ancient Warrior's Equipment\nZuriel's*\nVesta's*\nStatius's*\nMorrigan's*\n\n# Gauntlet Gear\nCrystal*(basic)\nCorrupted*\n*(perfected)\n*(attuned)\n\n# Max Cape\n*max cape*\n",
3 | "adjust_data": "USER OVERRIDES\n\n\nDEFAULT OVERRIDES\nGadderhammer: {\n\tattack: 1\n}\nFire battlestaff: {\n\tattack: 30\n \tmagic: 30\n}\nWater battlestaff: {\n\tattack: 30\n\tmagic: 30\n}\nAir battlestaff: {\n\tattack: 30\n\tmagic: 30\n}\nEarth battlestaff: {\n\tattack: 30\n\tmagic: 30\n}\nBattlestaff: {\n\tattack: 30\n\tmagic: 30\n}\nIvandis flail: {\n\tattack: 40\n\tslayer: 38\n\tstrength: 40\n\tmagic: 33\n}\n3rd age druidic staff: {\n\tprayer: 65\n\tattack: 65\n}\nMaple blackjack: {\n\tthieving: 30\n}\nMaple blackjack(o): {\n\tattack: 30\n\tthieving: 30\n}\nMaple blackjack(d): {\n\tdefence: 30\n\tthieving: 30\n}\nWestern banner 4: {\n\tranged: 70\n\tmagic: 64\n\tcmb: 100\n}\nWestern banner 3: {\n\tranged: 70,\n\tmagic: 64,\n\tattack: 42,\n\tdefence: 42,\n\thitpoints: 42,\n\tprayer: 22,\n\tstrength: 42,\n\tslayer: 93\n}\nWestern banner 2: {\n\tranged: 30,\n\tcmb: 70\n}\nWilderness sword 4: {\n\tmagic: 96,\n\tslayer: 83\n}\nWilderness sword 3: {\n\tmagic: 66,\n\tslayer: 68\n}\nWilderness sword 2: {\n\tmagic: 60,\n\tslayer: 50\n}\nShadow sword: {\n\tattack: 30,\n\tstrength: 30,\n\tmagic: 51,\n\tranged: 42\n}\nMythical cape: {\n\tmagic: 75,\n\thitpoints: 50,\n\tprayer: 42,\n\tstrength: 50,\n\tcmb: 85,\n\tslayer: 18,\n\tranged: 30\n}\nSpork: {\n\tattack: 10\n}\nFrying pan: {\n\tattack: 20\n}\nMeat tenderiser: {\n\tattack: 46,\n\tstrength: 47,\n\tdefence: 41\n}\nCleaver: {\n\tattack: 46,\n\tstrength: 47,\n\tdefence: 41\n}\nSpatula: {\n\tattack: 10\n}\nSkewer: {\n\tattack: 30\n}\nRolling pin: {\n\tattack: 40,\n\tdefence: 41\n}\nKatana: {\n\tattack: 40\n}\nAdamant Gloves: {\n\tdefence: 13\n}\nRune gloves: {\n\tdefence: 31\n}\nDragon gloves: {\n\tdefence: 41\n}\nBarrows gloves: {\t\n\tattack: 46,\n\tstrength: 47,\n\tdefence: 41\n}",
4 | "ignore_toggle": true,
5 | "adjust_toggle": false
6 | }
--------------------------------------------------------------------------------
/osrsmath/apps/optimize/data/monsters.json:
--------------------------------------------------------------------------------
1 | {
2 | "monsters": {},
3 | "potions": "none",
4 | "potion_attributes": "accuracy and damage",
5 | "boosting_scheme": "Constant",
6 | "below_skill": "attack",
7 | "redose_level": "7",
8 | "prayers": "none",
9 | "prayer_attributes": "accuracy and damage",
10 | "training_skill": "attack",
11 | "slayer_helm": false,
12 | "obsidian": false,
13 | "void_knight": false,
14 | "elite_void": false,
15 | "berserker_necklace": false,
16 | "dharok": "0",
17 | "salve_amulet": false,
18 | "show_histogram": false,
19 | "cpu_cores": "0"
20 | }
--------------------------------------------------------------------------------
/osrsmath/apps/optimize/data/player.json:
--------------------------------------------------------------------------------
1 | {
2 | "attack": "1",
3 | "defence": "1",
4 | "strength": "1",
5 | "hitpoints": "1",
6 | "ranged": "90",
7 | "prayer": "1",
8 | "magic": "1",
9 | "cooking": "",
10 | "woodcutting": "99",
11 | "fletching": "",
12 | "fishing": "99",
13 | "firemaking": "",
14 | "crafting": "",
15 | "smithing": "",
16 | "mining": "99",
17 | "herblore": "",
18 | "agility": "99",
19 | "thieving": "99",
20 | "slayer": "99",
21 | "farming": "",
22 | "runecraft": "",
23 | "hunter": "",
24 | "construction": "",
25 | "cmb": "44"
26 | }
--------------------------------------------------------------------------------
/osrsmath/apps/optimize/images/interface.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/optimize/images/interface.png
--------------------------------------------------------------------------------
/osrsmath/apps/optimize/logic/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/optimize/logic/__init__.py
--------------------------------------------------------------------------------
/osrsmath/apps/optimize/logic/evaluation.py:
--------------------------------------------------------------------------------
1 | from osrsmath.combat.fighter import Fighter
2 | from osrsmath.combat.experience import xp_rate
3 | import multiprocess
4 | import time
5 |
6 | def mmap(f, items, callback, interval=0.025, num_cores=0):
7 | """ num_cores: None or 0 mean maximum ("the number returned by `os.cpu_count()`").
8 | @see https://docs.python.org/3/library/multiprocessing.html#multiprocessing.pool.Pool
9 | """
10 | results = []
11 | start = time.time()
12 | with multiprocess.Pool(num_cores if num_cores != 0 else None) as pool:
13 | for i, result in enumerate(pool.imap_unordered(f, items), 1):
14 | results.append(result)
15 | now = time.time()
16 | if now-start >= interval:
17 | start = now
18 | callback(i/len(items)*100)
19 | callback(100)
20 | # pool.clear() # Using close/join crashes the app on the next iteration, ProcessPool must effect the global space.
21 | return results
22 |
23 | def eval_set(fighter, training_skill, states, defenders, s, include_shared_xp=True):
24 | combat_style, s = s
25 | fighter.equipment.wear(*s.values())
26 | fighter.set_stance(combat_style)
27 | xp = xp_rate(
28 | fighter.get_attack_style(),
29 | fighter.get_attack_speed(),
30 | states(fighter),
31 | defenders,
32 | 'MarkovChain'
33 | )
34 | # print(s, '|', f"{xp/1000:.2f}")
35 | return s, xp, combat_style
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/osrsmath/apps/optimize/logic/gear.py:
--------------------------------------------------------------------------------
1 | from osrsmath.combat.equipment import EquipmentPool
2 | from osrsmath.combat.fighter import bonus_to_triangle
3 | from collections import defaultdict
4 | import fnmatch
5 |
6 | def has_offensive_bonuses(armour, triangle):
7 | def bool_from_stats(stats):
8 | return any(
9 | amount > 0 for bonus, amount in armour['equipment'].items() if bonus in stats
10 | ) and armour['equipable_by_player']
11 |
12 | if triangle.lower() == 'melee':
13 | return bool_from_stats(["attack_crush", "attack_slash", "attack_stab", "melee_strength"])
14 | elif triangle.lower() == 'ranged':
15 | return bool_from_stats(["attack_ranged", "ranged_strength"])
16 | elif triangle.lower() == 'magic':
17 | return bool_from_stats(["attack_magic", "magic_damage"])
18 |
19 | def get_offensive_equipment(triangle):
20 | # Reduce the equipment to only those that have a) offensive bonuses, b) melee bonuses
21 | # Filter for only melee weapons since other attack styles aren't handled yet
22 | # Also only equipment that gives offensive bonuses, since that is what we're optimizing
23 | offensive_equipment = defaultdict(list)
24 | for slot, equipment in EquipmentPool().equipment.items():
25 | if slot == "weapon" or slot == "2h":
26 | for weapon in equipment.values():
27 | if has_offensive_bonuses(weapon, triangle):
28 | offensive_equipment[slot].append(weapon)
29 | else:
30 | for armour in equipment.values():
31 | if has_offensive_bonuses(armour, triangle):
32 | offensive_equipment[slot].append(armour)
33 | return offensive_equipment
34 |
35 | def get_offensive_bonuses(equipment, attack_style):
36 | bonuses = {}
37 | if equipment['weapon']:
38 | # Use reciprocal since a greater 1/attack_speed is better,
39 | # and comparisons are done using >.
40 | bonuses.update({'reciprocal_attack_speed': 1/equipment['weapon']['attack_speed']})
41 |
42 | allowed = [f"attack_{attack_style}", {
43 | 'melee': "melee_strength",
44 | 'ranged': "ranged_strength",
45 | 'magic': "magic_damage",
46 | }[bonus_to_triangle(attack_style)]
47 | ]
48 | bonuses.update({stat:value for stat, value in equipment['equipment'].items() if stat in allowed})
49 | return bonuses
50 |
51 | def meets_requirements(player_stats, equipment):
52 | if equipment['equipment']['requirements'] is None:
53 | return True
54 | for stat, req in equipment['equipment']['requirements'].items():
55 | if stat not in player_stats:
56 | raise ValueError(f"Supply your {stat} level to check {equipment['name']} for: {equipment['equipment']['requirements']}")
57 | if player_stats[stat] < req:
58 | return False
59 | return True
60 |
61 | def get_equipable_gear(training_skill, gear, player_stats, ignore, adjustments):
62 | equipable = defaultdict(list)
63 | for slot, slot_equipment in gear.items():
64 | for equipment in slot_equipment:
65 | if any(fnmatch.fnmatch(equipment['name'], item) for item in ignore): # matches with wildcard support
66 | continue
67 |
68 | if equipment['name'] in adjustments:
69 | equipment['equipment']['requirements'] = adjustments[equipment['name']]
70 |
71 | # If you satisfy a requirement, you can make it None, and choose only from that group
72 | if equipment['equipment']['requirements']:
73 | if meets_requirements(player_stats, equipment):
74 | equipment['equipment']['requirements'] = None
75 | else:
76 | continue
77 |
78 | # You must be able to train the desired skill, if you are a weapon
79 | if slot == '2h' or slot == 'weapon':
80 | if not any(Weapon.stance_can_train(stance, training_skill) \
81 | for stance in equipment['weapon']['stances']):
82 | continue
83 | equipable[slot].append(equipment)
84 | return equipable
85 |
86 | class Weapon:
87 | @staticmethod
88 | def stance_can_train(stance: dict, skill):
89 | if stance['experience'] is None: # Like Dinh's bulwark, on block
90 | return False
91 |
92 | if stance['experience'] == 'shared': # Melee
93 | return skill == 'controlled'
94 | return skill == stance['experience']
95 |
96 | @staticmethod
97 | def stance_can_use(stance, attack_type):
98 | assert attack_type in ['stab', 'slash', 'crush', 'ranged', 'magic']
99 | if stance['attack_type'] is None:
100 | if stance['experience'] is None: # Dinh's bulwark
101 | return False
102 | return attack_type in stance['experience'] # Ranged
103 | if stance['attack_type'] in ('defensive casting', 'spellcasting'):
104 | return True
105 | else:
106 | return stance['attack_type'] == attack_type
107 |
108 |
109 | @staticmethod
110 | def stance_can_do(stance, skill, attack_type):
111 | train = Weapon.stance_can_train(stance, skill)
112 | use = Weapon.stance_can_use(stance, attack_type)
113 | return train and use
114 |
115 | def __init__(self, weapon):
116 | self.weapon = weapon
117 |
118 | def can_train(self, skill):
119 | return bool(self.get_skill_stances(skill))
120 |
121 | def get_skill_stances(self, skill):
122 | return [stance for stance in self.weapon['weapon']['stances']
123 | if Weapon.stance_can_train(stance, skill)]
124 |
--------------------------------------------------------------------------------
/osrsmath/apps/optimize/logic/utility.py:
--------------------------------------------------------------------------------
1 | from pprint import pprint
2 |
3 | def get_maximum_sets(groups, getter=None):
4 | ''' Takes in a list of tuples and returns the subset containing the unique maximums.
5 | @param groups: [(A, B), (C, D), ... (Y, Z)]
6 | @param getter: A function which accesses the element of (A) to be compared.
7 | @return [(A, B), (E, F), (M, N)]
8 | @note When the group elements are single-length tuples,
9 | this degenerates into the max function.
10 | @warning Fails if there are duplicate items. '''
11 | def is_better(element, other):
12 | if getter:
13 | element = getter(element)
14 | other = getter(other)
15 | if all(o == e for e, o in zip(element, other)):
16 | return False
17 | return not any(o > e for e, o in zip(element, other))
18 |
19 | def someone_is_better(element, others):
20 | return any(is_better(other, element) for other in others
21 | if element is not other)
22 |
23 | return [element for element in groups if not someone_is_better(element, groups)]
24 |
25 |
26 | if __name__ == '__main__':
27 | print(get_maximum_sets([(1, 4), (1, 5), (1, 5)]), [(1, 5)])
28 | print(get_maximum_sets([(1, 4), (1, 5)]), [(1, 5)])
29 | print(get_maximum_sets([(1, 4), (1, 5), (2, 6)]), [(2, 6)])
30 | print(get_maximum_sets([
31 | {
32 | 'name': 'test1',
33 | 'values': (1, 4),
34 | }, {
35 | 'name': 'test2',
36 | 'values': (1, 5),
37 | }, {
38 | 'name': 'test3',
39 | 'values': (2, 6),
40 | },
41 | ], lambda x: x['values']))
42 |
43 | print(get_maximum_sets([(1, 4), (1, 5), (3, 4)]), [(1, 5), (3, 4)])
44 |
45 | print(get_maximum_sets([
46 | (0.16, -4, 85),
47 | (0.16, -2, 85),
48 | (0.16, 2, 0),
49 | (0.16, 11, 13),
50 | (0.16, 12, 68),
51 | ]))
--------------------------------------------------------------------------------
/osrsmath/apps/optimize/panels/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/optimize/panels/__init__.py
--------------------------------------------------------------------------------
/osrsmath/apps/optimize/panels/player.py:
--------------------------------------------------------------------------------
1 | from osrsmath.apps.GUI.optimize.player_skeleton import Ui_Form
2 | from osrsmath.apps.GUI.shared.widgets import Savable
3 | from osrsmath.general.skills import get_skills, get_combat_skills
4 | from osrsmath.general.skills import combat_level
5 | from PySide6 import QtCore, QtGui, QtWidgets
6 |
7 | class PlayerPanel(QtWidgets.QWidget, Ui_Form, Savable):
8 | def __init__(self, parent=None):
9 | super().__init__(parent)
10 | self.setupUi(self)
11 | self.entities = {
12 | skill: Savable.Entity(
13 | getattr(self, skill),
14 | '',
15 | lambda o, v: o.setText(v),
16 | lambda o: o.text()
17 | ) for skill in get_skills(lower=True)
18 | }
19 | self.entities['cmb'] = Savable.Entity(
20 | self.combat_level, '', lambda o, v: o.setText(v), lambda o: o.text()
21 | )
22 |
23 | # Only integer input allowed for skill levels
24 | for skill in get_skills(lower=True):
25 | self.entities[skill].object.setValidator(QtGui.QIntValidator(1, 99))
26 |
27 | for skill in get_combat_skills(lower=True):
28 | self.entities[skill].object.editingFinished.connect(self.update_cmb_level)
29 |
30 | def update_cmb_level(self):
31 | try:
32 | self.entities['cmb'].set(str(combat_level(self.get_stats())))
33 | except ValueError as e:
34 | print(e)
35 | pass
36 |
37 |
38 | def get_stats(self):
39 | ''' Returns a dictionary of all displayed levels (including cmb). '''
40 | return {
41 | skill: int(self.entities[skill].get()) for skill in get_skills(lower=True) + ['cmb'] if self.entities[skill].get() != ''
42 | }
--------------------------------------------------------------------------------
/osrsmath/apps/path/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/path/__init__.py
--------------------------------------------------------------------------------
/osrsmath/apps/path/tree.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/path/tree.pdf
--------------------------------------------------------------------------------
/osrsmath/apps/path/tree_1def.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/apps/path/tree_1def.pdf
--------------------------------------------------------------------------------
/osrsmath/config.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import pathlib
4 | from pathlib import Path
5 |
6 | TOP = os.path.join(os.path.dirname(sys.argv[0]), 'DATA') if getattr(sys, 'frozen', False) else os.path.dirname(__file__)
7 | DATA_PATH = os.path.join(TOP, 'combat', 'data')
8 | RESULTS_PATH = os.path.join(TOP, 'results')
9 |
10 | def resource_path(path):
11 | return Path(TOP)/path
12 |
13 | def get_figure(a=None, e=None, scale=10):
14 | """ Creates the desired figure setup:
15 | 1) Maximize Figure
16 | 2) Create 3D Plotting Environment
17 | 3) Rotate Z axis label so it is upright
18 | 4) Let labels
19 | 5) Increase label font size
20 | 6) Rotate camera to ideal (predetermined) angle """
21 | from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import
22 | import matplotlib.pyplot as plt
23 | import matplotlib as mpl
24 | mpl.rcParams["savefig.directory"] = "."
25 |
26 | fig = plt.figure()
27 | fig.set_size_inches(1920/1080*scale, scale)
28 | ax = fig.add_subplot(111, projection='3d')
29 | ax.zaxis.set_rotate_label(False) # disable automatic rotation, otherwise you can't manually override
30 | ax.xaxis._axinfo['label']['space_factor'] = 6.8
31 | ax.yaxis._axinfo['label']['space_factor'] = 4.8
32 | ax.zaxis._axinfo['label']['space_factor'] = 4.8
33 | ax.view_init(azim=a, elev=e)
34 | return fig, ax
35 |
--------------------------------------------------------------------------------
/osrsmath/docs/latex/.ipynb_checkpoints/main-checkpoint.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/.ipynb_checkpoints/main-checkpoint.pdf
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/Older/Details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/Older/Details.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/Older/Equipment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/Older/Equipment.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/Older/NMZ.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/Older/NMZ.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/Older/Stats.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/Older/Stats.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/Older/fig_time.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/Older/fig_time.pdf
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/Older/levels_recur.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/Older/levels_recur.pdf
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/Older/levels_recur_10_10.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/Older/levels_recur_10_10.pdf
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/Older/levels_recur_60_90.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/Older/levels_recur_60_90.pdf
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/Older/training_scheme.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/Older/training_scheme.pdf
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/combat/Combat_triangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/combat/Combat_triangle.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/combat/Equipment_Stats_interface_and_triangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/combat/Equipment_Stats_interface_and_triangle.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/combat/bandos.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/combat/bandos.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/combat/bandos_one_shot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/combat/bandos_one_shot.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/combat/bandos_slim.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/combat/bandos_slim.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/combat/damage_distributions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/combat/damage_distributions.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/combat/defence_training.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/combat/defence_training.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/combat/fight_outcome_probabilities.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/combat/fight_outcome_probabilities.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/combat/gear_optimizer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/combat/gear_optimizer.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/combat/training_graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/combat/training_graph.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/combat/training_order60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/combat/training_order60.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/combat/training_order_sequence.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/combat/training_order_sequence.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/firemaking/wintertodt_actions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/firemaking/wintertodt_actions.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/skill_capes/Firemaking_cape_detail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/skill_capes/Firemaking_cape_detail.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/skill_capes/Howling_Snow_Storm-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/skill_capes/Howling_Snow_Storm-0.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/skill_capes/Howling_Snow_Storm-0.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/skill_capes/Howling_Snow_Storm-0.xcf
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/skill_capes/Howling_Snow_Storm.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/skill_capes/Howling_Snow_Storm.gif
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/skill_capes/transparent_Howling_Snow_Storm-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/skill_capes/transparent_Howling_Snow_Storm-0.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/skills/Construction_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/skills/Construction_icon.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/skills/Farming_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/skills/Farming_icon.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/skills/Firemaking_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/skills/Firemaking_icon.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/skills/Fletching_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/skills/Fletching_icon.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/skills/Herblore_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/skills/Herblore_icon.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/skills/Woodcutting_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/skills/Woodcutting_icon.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/skills/blank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/skills/blank.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/skills_quest_player.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/skills_quest_player.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/general/wildmudkip_maxing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/general/wildmudkip_maxing.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/mining/optimal_order.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/mining/optimal_order.pdf
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/mining/varying_paydirt.100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/mining/varying_paydirt.100.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/quests/osrs_by_requirement.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/quests/osrs_by_requirement.pdf
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/quests/universe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/quests/universe.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/quests/zoom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/quests/zoom.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/img/woodcutting/experience.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/img/woodcutting/experience.pdf
--------------------------------------------------------------------------------
/osrsmath/docs/latex/main.bbl:
--------------------------------------------------------------------------------
1 | \begin{thebibliography}{10}
2 |
3 | \bibitem{bestreamer:10_most_played_mmorpgs_of_2020}
4 | 10 most played mmorpgs of 2020.
5 | \newblock \url{https://bestreamer.com/gaming/most-played-mmorpg-2019/2/}.
6 | \newblock Retrieved October 02, 2020.
7 |
8 | \bibitem{altarofgaming:top_6_most_popular_mmorpgs}
9 | Top 6 most popular mmorpgs sorted by population (2020).
10 | \newblock \url{https://altarofgaming.com/all-mmos-sorted-by-population-2018/}.
11 | \newblock Retrieved October 02, 2020.
12 |
13 | \bibitem{thegamer:ranking_the_15_best_mmorpgs}
14 | Ranking the 15 best mmorpgs of all time.
15 | \newblock \url{https://www.thegamer.com/best-mmorpgs-ever-wow-runescape/}.
16 | \newblock Retrieved October 02, 2020.
17 |
18 | \bibitem{misplacedme:relative_player_counts}
19 | Misplacedme.
20 | \newblock Relative player counts in runescape.
21 | \newblock \url{https://www.misplaceditems.com/rs_tools/graph/}.
22 |
23 | \bibitem{wiki:skills}
24 | Wiki.
25 | \newblock Skills.
26 | \newblock \url{https://oldschool.runescape.wiki/w/Skills}.
27 |
28 | \bibitem{wiki:experience}
29 | Wiki.
30 | \newblock Experience.
31 | \newblock \url{https://oldschool.runescape.wiki/w/Experience}.
32 |
33 | \bibitem{wiki:quests}
34 | Wiki.
35 | \newblock Quests.
36 | \newblock \url{https://oldschool.runescape.wiki/w/Quests}.
37 |
38 | \bibitem{wiki:combat_triangle}
39 | Wiki.
40 | \newblock Combat triangle.
41 | \newblock \url{https://oldschool.runescape.wiki/w/Combat_triangle}.
42 |
43 | \bibitem{bitter:dps_calculator}
44 | Dps calculator by bitterkoekje.
45 | \newblock
46 | \url{https://docs.google.com/spreadsheets/d/1wzy1VxNWEAAc0FQyDAdpiFggAfn5U6RGPp2CisAHZW8/edit#gid=158500257}.
47 |
48 | \bibitem{nukelawe:osrs-markov}
49 | Nukelawe.
50 | \newblock Markov chain analysis of overkill and natural regeneration in osrs
51 | combat.
52 | \newblock \url{https://github.com/Nukelawe/osrs-markov/blob/master/main.pdf}.
53 |
54 | \bibitem{wiki:wintertodt_supply_crates}
55 | Wiki.
56 | \newblock Calculator:wintertodt supply crate.
57 | \newblock
58 | \url{https://oldschool.runescape.wiki/w/Calculator:Wintertodt_supply_crate}.
59 | \newblock Retrieved November 04, 2020.
60 |
61 | \bibitem{HereticAcinonyx:wintertodt_99_value}
62 | HereticAcinonyx.
63 | \newblock Loot from 50-99 fm at wintertodt post-nerf (level 1 skills).
64 | \newblock \url{https://imgur.com/r/2007scape/WKrov}.
65 |
66 | \bibitem{osrsbox:wintertodt_damage}
67 | OSRSBox.
68 | \newblock Analysis of wintertodt damage at 10 hitpoints.
69 | \newblock
70 | \url{https://www.osrsbox.com/blog/2020/07/04/analysing-wintertodt-damage-at-10-hitpoints/}.
71 |
72 | \end{thebibliography}
73 |
--------------------------------------------------------------------------------
/osrsmath/docs/latex/main.bib:
--------------------------------------------------------------------------------
1 | @misc{bestreamer:10_most_played_mmorpgs_of_2020,
2 | title = {10 Most Played MMORPGs of 2020},
3 | published = {2020, September 11},
4 | howpublished = {\url{https://bestreamer.com/gaming/most-played-mmorpg-2019/2/}},
5 | note = {Retrieved October 02, 2020}
6 | }
7 |
8 | @misc{altarofgaming:top_6_most_popular_mmorpgs,
9 | title = {Top 6 Most Popular MMORPGs Sorted by Population (2020)},
10 | published = {2020, June 8},
11 | howpublished = {\url{https://altarofgaming.com/all-mmos-sorted-by-population-2018/}},
12 | note = {Retrieved October 02, 2020}
13 | }
14 |
15 | @misc{thegamer:ranking_the_15_best_mmorpgs,
16 | title = {Ranking The 15 Best MMORPGs Of All Time},
17 | published = {2020, May 13},
18 | howpublished = {\url{https://www.thegamer.com/best-mmorpgs-ever-wow-runescape/}},
19 | note = {Retrieved October 02, 2020}
20 | }
21 |
22 | @misc{wiki:skills,
23 | title = {Skills},
24 | author = {Wiki},
25 | howpublished = {\url{https://oldschool.runescape.wiki/w/Skills}}
26 | }
27 |
28 | @misc{wiki:experience,
29 | title = {Experience},
30 | author = {Wiki},
31 | howpublished = {\url{https://oldschool.runescape.wiki/w/Experience}}
32 | }
33 |
34 | @misc{wiki:quests,
35 | title = {Quests},
36 | author = {Wiki},
37 | howpublished = {\url{https://oldschool.runescape.wiki/w/Quests}}
38 | }
39 |
40 | @misc{wiki:combat_triangle,
41 | title = {Combat Triangle},
42 | author = {Wiki},
43 | howpublished = {\url{https://oldschool.runescape.wiki/w/Combat_triangle}}
44 | }
45 |
46 | @misc{wiki:max_melee,
47 | title = {Maximum Melee Hit},
48 | author = {Wiki},
49 | howpublished = {\url{https://oldschool.runescape.wiki/w/Maximum_melee_hit}}
50 | }
51 |
52 | @misc{wiki:max_ranged,
53 | title = {Maximum Ranged Hit},
54 | author = {Wiki},
55 | howpublished = {\url{https://oldschool.runescape.wiki/w/Maximum_ranged_hit}}
56 | }
57 |
58 | @misc{wiki:max_magic,
59 | title = {Maximum Magic Hit},
60 | author = {Wiki},
61 | howpublished = {\url{https://oldschool.runescape.wiki/w/Maximum_magic_hit}}
62 | }
63 |
64 | @misc{wiki:max_hit,
65 | title = {Maximum Hit},
66 | author = {Wiki},
67 | howpublished = {\url{https://oldschool.runescape.wiki/w/Maximum_hit}}
68 | }
69 |
70 | @misc{wiki:attribute,
71 | title = {Monster Attribute},
72 | author = {Wiki},
73 | howpublished = {\url{https://oldschool.runescape.wiki/w/Monster_attribute}}
74 | }
75 |
76 | @misc{bitter:dps_calculator,
77 | title = {DPS calculator by Bitterkoekje},
78 | howpublished = {\url{https://docs.google.com/spreadsheets/d/1wzy1VxNWEAAc0FQyDAdpiFggAfn5U6RGPp2CisAHZW8/edit#gid=158500257}}
79 | }
80 |
81 | @misc{misplacedme:relative_player_counts,
82 | title = {Relative Player Counts in Runescape},
83 | author = {Misplacedme},
84 | howpublished = {\url{https://www.misplaceditems.com/rs_tools/graph/}}
85 | }
86 |
87 | @misc{wiki:wintertodt_supply_crates,
88 | title = {Calculator:Wintertodt supply crate},
89 | author = {Wiki},
90 | howpublished = {\url{https://oldschool.runescape.wiki/w/Calculator:Wintertodt_supply_crate}},
91 | note = {Retrieved November 04, 2020}
92 | }
93 |
94 | @misc{HereticAcinonyx:wintertodt_99_value,
95 | title = {Loot From 50-99 Fm at Wintertodt Post-NERF (Level 1 Skills)},
96 | author = {HereticAcinonyx},
97 | howpublished = {\url{https://imgur.com/r/2007scape/WKrov}}
98 | }
99 |
100 | @misc{osrsbox:wintertodt_damage,
101 | title = {Analysis of Wintertodt Damage at 10 Hitpoints},
102 | author = {OSRSBox},
103 | howpublished = {\url{https://www.osrsbox.com/blog/2020/07/04/analysing-wintertodt-damage-at-10-hitpoints/}}
104 | }
105 |
106 | @misc{nukelawe:osrs-markov,
107 | title = {Markov chain analysis of overkill and natural regeneration in OSRS combat},
108 | author = {Nukelawe},
109 | howpublished = {\url{https://github.com/Nukelawe/osrs-markov/blob/master/main.pdf}}
110 | }
111 |
112 |
113 |
--------------------------------------------------------------------------------
/osrsmath/docs/latex/main.blg:
--------------------------------------------------------------------------------
1 | This is BibTeX, Version 0.99d (TeX Live 2019/Debian)
2 | Capacity: max_strings=200000, hash_size=200000, hash_prime=170003
3 | The top-level auxiliary file: main.aux
4 | The style file: unsrt.bst
5 | Database file #1: main.bib
6 | You've used 13 entries,
7 | 1791 wiz_defined-function locations,
8 | 491 strings with 5238 characters,
9 | and the built_in function-call counts, 1583 in all, are:
10 | = -- 130
11 | > -- 40
12 | < -- 0
13 | + -- 22
14 | - -- 9
15 | * -- 2
16 | := -- 226
17 | add.period$ -- 39
18 | call.type$ -- 13
19 | change.case$ -- 13
20 | chr.to.int$ -- 0
21 | cite$ -- 13
22 | duplicate$ -- 65
23 | empty$ -- 235
24 | format.name$ -- 9
25 | if$ -- 387
26 | int.to.chr$ -- 0
27 | int.to.str$ -- 13
28 | missing$ -- 0
29 | newline$ -- 68
30 | num.names$ -- 9
31 | pop$ -- 77
32 | preamble$ -- 1
33 | purify$ -- 0
34 | quote$ -- 0
35 | skip$ -- 56
36 | stack$ -- 0
37 | substring$ -- 0
38 | swap$ -- 13
39 | text.length$ -- 0
40 | text.prefix$ -- 0
41 | top$ -- 0
42 | type$ -- 0
43 | warning$ -- 0
44 | while$ -- 9
45 | width$ -- 15
46 | write$ -- 119
47 |
--------------------------------------------------------------------------------
/osrsmath/docs/latex/main.out:
--------------------------------------------------------------------------------
1 | \BOOKMARK [1][-]{Item.3}{Introduction}{}% 1
2 | \BOOKMARK [-1][-]{part.1}{I General}{}% 2
3 | \BOOKMARK [0][-]{chapter.1.1}{Experience and Levels}{part.1}% 3
4 | \BOOKMARK [-1][-]{part.2}{II Combat}{}% 4
5 | \BOOKMARK [0][-]{chapter.2.1}{Overview}{part.2}% 5
6 | \BOOKMARK [1][-]{section.2.1.1}{Autonomous Mechanics}{chapter.2.1}% 6
7 | \BOOKMARK [2][-]{subsection.2.1.1.1}{Combat Skills, Combat Triangle and Attack Styles}{section.2.1.1}% 7
8 | \BOOKMARK [2][-]{subsection.2.1.1.2}{Equipment Bonuses}{section.2.1.1}% 8
9 | \BOOKMARK [2][-]{subsection.2.1.1.3}{Max Hits and Accuracy}{section.2.1.1}% 9
10 | \BOOKMARK [2][-]{subsection.2.1.1.4}{Ticks and Attack Speed}{section.2.1.1}% 10
11 | \BOOKMARK [2][-]{subsection.2.1.1.5}{Summary}{section.2.1.1}% 11
12 | \BOOKMARK [1][-]{section.2.1.2}{Agency \046 Decisions}{chapter.2.1}% 12
13 | \BOOKMARK [2][-]{subsection.2.1.2.1}{Actions}{section.2.1.2}% 13
14 | \BOOKMARK [2][-]{subsection.2.1.2.2}{Machine Learning}{section.2.1.2}% 14
15 | \BOOKMARK [2][-]{subsection.2.1.2.3}{Genetic Algorithm}{section.2.1.2}% 15
16 | \BOOKMARK [0][-]{chapter.2.2}{Models}{part.2}% 16
17 | \BOOKMARK [1][-]{section.2.2.1}{Crude Model}{chapter.2.2}% 17
18 | \BOOKMARK [2][-]{subsection.2.2.1.1}{Health after \040attacks}{section.2.2.1}% 18
19 | \BOOKMARK [2][-]{subsection.2.2.1.2}{Attacks until \040health}{section.2.2.1}% 19
20 | \BOOKMARK [1][-]{section.2.2.2}{Average}{chapter.2.2}% 20
21 | \BOOKMARK [2][-]{subsection.2.2.2.1}{Average Damage}{section.2.2.2}% 21
22 | \BOOKMARK [2][-]{subsection.2.2.2.2}{Attacks to kill}{section.2.2.2}% 22
23 | \BOOKMARK [1][-]{section.2.2.3}{Recursive Model}{chapter.2.2}% 23
24 | \BOOKMARK [2][-]{subsection.2.2.3.1}{Expected Damage per Hit}{section.2.2.3}% 24
25 | \BOOKMARK [2][-]{subsection.2.2.3.2}{Health after \040attacks}{section.2.2.3}% 25
26 | \BOOKMARK [2][-]{subsection.2.2.3.3}{Attacks until \040health}{section.2.2.3}% 26
27 | \BOOKMARK [1][-]{section.2.2.4}{Approximately Analytic Recursion}{chapter.2.2}% 27
28 | \BOOKMARK [2][-]{subsection.2.2.4.1}{Health after \040attacks}{section.2.2.4}% 28
29 | \BOOKMARK [2][-]{subsection.2.2.4.2}{Attacks until \040health}{section.2.2.4}% 29
30 | \BOOKMARK [1][-]{section.2.2.5}{Health Regeneration}{chapter.2.2}% 30
31 | \BOOKMARK [1][-]{section.2.2.6}{Comparisons}{chapter.2.2}% 31
32 | \BOOKMARK [0][-]{chapter.2.3}{Markov Chain Solutions}{part.2}% 32
33 | \BOOKMARK [1][-]{section.2.3.1}{Damage Distributions}{chapter.2.3}% 33
34 | \BOOKMARK [1][-]{section.2.3.2}{Recursive Equation}{chapter.2.3}% 34
35 | \BOOKMARK [1][-]{section.2.3.3}{Solution}{chapter.2.3}% 35
36 | \BOOKMARK [2][-]{subsection.2.3.3.1}{Interior}{section.2.3.3}% 36
37 | \BOOKMARK [2][-]{subsection.2.3.3.2}{Obtaining Power Series}{section.2.3.3}% 37
38 | \BOOKMARK [2][-]{subsection.2.3.3.3}{Applying Boundary Conditions}{section.2.3.3}% 38
39 | \BOOKMARK [1][-]{section.2.3.4}{Fight Outcomes}{chapter.2.3}% 39
40 | \BOOKMARK [0][-]{chapter.2.4}{Optimizing Player Equipment}{part.2}% 40
41 | \BOOKMARK [1][-]{section.2.4.1}{The Projection Vector}{chapter.2.4}% 41
42 | \BOOKMARK [1][-]{section.2.4.2}{Set Reduction}{chapter.2.4}% 42
43 | \BOOKMARK [1][-]{section.2.4.3}{Gear Optimization Implementation \046 GUI}{chapter.2.4}% 43
44 | \BOOKMARK [0][-]{chapter.2.5}{Optimizing Training Order}{part.2}% 44
45 | \BOOKMARK [1][-]{section.2.5.1}{Dijkstra's algorithm}{chapter.2.5}% 45
46 | \BOOKMARK [0][-]{section*.19}{Appendices}{part.2}% 46
47 | \BOOKMARK [0][-]{appendix.1.A}{Justifying the Recursive Model Approximation}{part.2}% 47
48 | \BOOKMARK [0][-]{appendix.1.B}{Power Reduction in the Piecewise Recursive Model}{part.2}% 48
49 | \BOOKMARK [1][-]{section.1.B.1}{Power Reduction}{appendix.1.B}% 49
50 | \BOOKMARK [1][-]{section.1.B.2}{Simplifying}{appendix.1.B}% 50
51 | \BOOKMARK [-1][-]{part.3}{III Woodcutting}{}% 51
52 | \BOOKMARK [0][-]{appendix.3.1}{Traditional Woodcutting}{part.3}% 52
53 | \BOOKMARK [-1][-]{part.4}{IV Firemaking}{}% 53
54 | \BOOKMARK [0][-]{appendix.4.1}{Wintertodt}{part.4}% 54
55 | \BOOKMARK [1][-]{section.4.1.1}{Large groups}{appendix.4.1}% 55
56 | \BOOKMARK [2][-]{subsection.4.1.1.1}{Within a Fight}{section.4.1.1}% 56
57 | \BOOKMARK [2][-]{subsection.4.1.1.2}{Across Fights}{section.4.1.1}% 57
58 | \BOOKMARK [2][-]{subsection.4.1.1.3}{Kill Count, Time to Level, and Reward Value}{section.4.1.1}% 58
59 | \BOOKMARK [1][-]{section.4.1.2}{Future Work}{appendix.4.1}% 59
60 | \BOOKMARK [-1][-]{part.5}{V Mining}{}% 60
61 | \BOOKMARK [0][-]{appendix.5.1}{Motherload Mine}{part.5}% 61
62 | \BOOKMARK [-1][-]{part.6}{VI Quests}{}% 62
63 | \BOOKMARK [0][-]{appendix.6.1}{Graph/Network Analysis}{part.6}% 63
64 | \BOOKMARK [-1][-]{part.7}{VII Chunks}{}% 64
65 | \BOOKMARK [0][-]{appendix.7.1}{Solving the Lumbridge Chunk}{part.7}% 65
66 |
--------------------------------------------------------------------------------
/osrsmath/docs/latex/main.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/main.pdf
--------------------------------------------------------------------------------
/osrsmath/docs/latex/main.tex:
--------------------------------------------------------------------------------
1 | % Compile this with "pdflatex main.tex".
2 | % The allow the date to be fixed, compile the title page with "pdflatex tex/title.tex".
3 |
4 | \documentclass[10pt,a4paper]{report}
5 | \usepackage{mystyle}
6 | \usepackage[margin=1.5in]{geometry}
7 | \usepackage{amsmath}
8 | \usepackage{pdfpages}
9 | \usepackage[toc,page]{appendix}
10 | \graphicspath{{../../}} % examples/ will reference results.
11 | \usepackage{xr}
12 |
13 | %%% Multiple Appendicies
14 | \makeatletter
15 | \@addtoreset{chapter}{part}
16 | \@addtoreset{@ppsaveapp}{part}
17 | \makeatother
18 |
19 | % \renewcommand\maketitle{} % https://tex.stackexchange.com/questions/362202/latex-error-no-title-given-for-latex-output-by-lyx
20 | \usepackage{pdfpages}
21 | % \input{tex/title}
22 | \begin{document}
23 | % \maketitle
24 | \includepdf{tex/title}
25 | \tableofcontents
26 | \newpage
27 |
28 | This text accompanies several additional resources:
29 | \begin{enumerate}
30 | \item Python open-source codebase, \textit{OSRSmath}: \url{https://github.com/Palfore/OSRSmath}.
31 | \item Video Series, \textit{Optimizing Runescape}: \url{https://www.youtube.com/watch?v=7N9UJX70Z5I&list=PLm3INE_scU5s8NQWmw0fxKtA_6SVxDOc7&ab_channel=Palfore}.
32 | \item Discord Chatroom: \url{https://discord.gg/4SXcKQh}
33 | \end{enumerate}
34 |
35 | \newpage
36 | \section*{Introduction}
37 | \addcontentsline{toc}{section}{Introduction}
38 | \input{tex/introduction.tex}
39 |
40 | \part{General}
41 | \chapter{Experience and Levels}\label{chp:experience_and_levels}
42 | \input{tex/general/experience_and_levels.tex}
43 |
44 | \part{Combat}
45 | \input{tex/combat/list_of_terms.tex}
46 | \input{tex/combat/overview.tex}
47 | \input{tex/combat/models.tex}
48 | \input{tex/combat/markov_chain.tex}
49 | \chapter{Optimizing Player Equipment}
50 | \input{tex/combat/optimizing_player_equipment}
51 | \chapter{Optimizing Training Order}
52 | \input{tex/combat/optimal_training_order}
53 |
54 | \begin{appendices}
55 | \chapter{Justifying the Recursive Model Approximation}\label{combat-app:recursive_justification}
56 | \input{tex/combat/appendix/recursive_approximation}
57 | \chapter{Power Reduction in the Piecewise Recursive Model}\label{combat-app:power_reduction}
58 | \input{tex/combat/appendix/power_reduction}
59 | \end{appendices}
60 |
61 | \part{Woodcutting}
62 | \chapter{Traditional Woodcutting}
63 | \input{tex/woodcutting/woodcutting}
64 |
65 | \part{Firemaking}
66 | \chapter{Wintertodt}
67 | \input{tex/firemaking/wintertodt}
68 |
69 | \part{Mining}
70 | \chapter{Motherload Mine}
71 | \input{tex/mining/mining}
72 |
73 | \part{Quests}
74 | \chapter{Graph/Network Analysis}
75 | \input{tex/quests/quests}
76 |
77 |
78 | \part{Chunks}
79 | \chapter{Solving the Lumbridge Chunk}
80 | \includepdf[pages=-]{tex/chunks/ChunkSolver.pdf}
81 | % \markdownInput{{tex/chunks/ChunkSolver.md}
82 |
83 |
84 | \bibliographystyle{unsrt}
85 | \bibliography{main}
86 |
87 | \end{document}
--------------------------------------------------------------------------------
/osrsmath/docs/latex/mystyle.sty:
--------------------------------------------------------------------------------
1 | \ProvidesPackage{mystyle}
2 |
3 | %%% Hyperreferences %%%
4 | \usepackage{hyperref} % Used to be bookmarks
5 | \hypersetup{
6 | colorlinks=true,
7 | linkcolor=blue,
8 | linktoc=all,
9 | }
10 |
11 | %%% Basic Packages %%%
12 | \usepackage[table,xcdraw]{xcolor}
13 | \usepackage{makecell}
14 | \usepackage{multirow}
15 | \usepackage{subcaption}
16 | \usepackage{tikz}
17 | \usepackage{mathtools}
18 | \usepackage{empheq}
19 | \usetikzlibrary{decorations.pathreplacing,angles,quotes}
20 |
21 | \usepackage{cancel}
22 | \usepackage[utf8]{inputenc}
23 | \usepackage{amssymb} % Math Symbols
24 | \usepackage{amsmath}
25 | \usepackage{subfiles} % Subfiles
26 | \usepackage{dirtree} % Graphical File Hierarchy
27 | \usepackage{listings} % Code listings
28 | \usepackage{graphicx} % Includegraphics
29 | \usepackage{float} % Graphics Formatting
30 | \usepackage[nodayofweek]{datetime} % Dateformating
31 | \usepackage[font=footnotesize,labelfont=bf, margin=0cm]{caption} % Captions
32 | \usepackage{textcomp} % Allows for 'upquote' in code listings
33 | \usepackage{tocloft} % For defining TOC-like lists
34 | \usepackage{titlesec}
35 | \usepackage[toc, page, title]{appendix} % Appendix
36 | \usepackage{tabularx} % Better Table Environment
37 | \usepackage{ltablex} % Better Table Environment with longer tables
38 | \usepackage{booktabs} % Table row seperators
39 |
40 |
41 |
42 |
43 | %%% Colors %%%
44 | % \usepackage[dvipsnames]{xcolor}
45 | % \definecolor{level-1}{RGB}{53, 130, 255}
46 | % \definecolor{level-2}{RGB}{229, 64, 64}
47 | % \definecolor{level-3}{RGB}{67, 173, 69}
48 |
49 | % \definecolor{nice-green}{rgb}{0.01, 0.75, 0.24}
50 |
51 | \definecolor{mygreen}{rgb}{0,0.6,0}
52 | \definecolor{mygray}{rgb}{0.5,0.5,0.5}
53 | \definecolor{mymauve}{rgb}{0.58,0,0.82}
54 |
55 |
56 | %%% Code Listing Settings %%%
57 | \lstset{
58 | captionpos=b,
59 | basicstyle=\footnotesize, % the size of the fonts that are used for the code
60 | breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace
61 | breaklines=true, % sets automatic line breaking
62 | commentstyle=\color{mygreen}, % comment style
63 | frame=single, % adds a frame around the code
64 | keepspaces=true, % keeps spaces in text, useful for keeping indentation of code (possibly needs columns=flexible)
65 | keywordstyle=\color{blue}, % keyword style
66 | language=Python, % the language of the code
67 | numbers=left, % where to put the line-numbers; (none, left, right)
68 | numbersep=5pt, % how far the line-numbers are from the code
69 | numberstyle=\small\color{mygray}, % the style that is used for the line-numbers
70 | showspaces=false, % show spaces everywhere adding particular underscores; it overrides 'showstringspaces'
71 | showstringspaces=false, % underline spaces within strings only
72 | showtabs=false, % show tabs within strings adding particular underscores
73 | stepnumber=1, % the step between two line-numbers. If it's 1, each line will be numbered
74 | stringstyle=\color{mymauve}, % string literal style
75 | tabsize=2, % sets default tabsize to 2 spaces
76 | title=\lstname, % show the filename of files included with \lstinputlisting; also try caption instead of title
77 | upquote=true
78 | }
79 |
80 |
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/chunks/ChunkSolver.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/tex/chunks/ChunkSolver.md
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/chunks/ChunkSolver.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/tex/chunks/ChunkSolver.pdf
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/chunks/image-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/tex/chunks/image-2.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/chunks/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/tex/chunks/image.png
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/combat/appendix/recursive_approximation.tex:
--------------------------------------------------------------------------------
1 | We begin with Eq.~(\ref{eq:simplified_recursion}) which we will restate here with $h_m\to x_n$:
2 | \begin{align}
3 | x_{n+1} = x_n - \frac{x_n}{2}\left(2 - \frac{x_n + 1}{M+1} \right).
4 | \end{align}
5 | This formulation looks similar to Newtons method for finding the root of $f(x)$, which is given as
6 | \begin{align}
7 | x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)}.
8 | \end{align}
9 | After some algebra we find that,
10 | \begin{align}
11 | \frac{f(x_n)}{f'(x_n)} = x_n(1-\gamma x_n).
12 | \end{align}
13 | This can be easily solved for $f(x)$ since this is a separable equation:
14 | \begin{align}
15 | \frac{df}{f} &= \frac{dx}{x(1-\gamma x)} \\
16 | \int \frac{df}{f} &= \int \frac{dx}{x(1-\gamma x)} \\
17 | \ln(f) &= \ln|x| - \ln|\gamma x - 1| + C \\
18 | f(x) &= e^C |x||\gamma x - 1|
19 | \end{align}
20 | The error, $\epsilon$ in the next iteration of Newtons method is given as,
21 | \begin{align}
22 | \epsilon_{n+1} = \epsilon_{n}^2 \left | \frac{f''(r)}{2f'(r)} \right |,
23 | \end{align}
24 | where $r$ is the root we desire. In this case the root we want is,
25 | \begin{align}
26 | \lim_{n\to\infty} x_n = 0
27 | \end{align}
28 | since this corresponds to the health reaching zero. The ratio becomes,
29 | \begin{align}
30 | \left| \frac{f''(r)}{2f'(r)} \right| = \gamma,
31 | \end{align}
32 | which simplifies the error equation to,
33 | \begin{align}
34 | \epsilon_{n+1} = \gamma \epsilon_{n}^2.
35 | \end{align}
36 | This is exactly the same recursive equation we had before! Except that now we have error in health instead of health. So how does this connect? Since we already know the root value (which is 0), the error becomes the upper bound on the health. This means that if we have an error of, for example, 1 that the health must be below that. So, by solving $\epsilon=h$ we can find the number of iterations required to reach below that health. This solution is already given earlier but in the context of error we have,
37 | \begin{align}
38 | \epsilon_{n} = \frac{1}{\gamma}\left( \frac{1}{2} - \gamma \right)^{2^{n}} \\
39 | n = \log_2 \log_{\frac{1}{2} - \gamma} (\gamma \epsilon).
40 | \end{align}
41 | This has done two things: justify the use exclusion of the $h_m$ term in the original recursive equation (instead of excluding $h^2_m$), and provided a second interpretation of the meaning of $h = 1$. The error comes from a Taylor series, but interestingly all higher order terms die off so this is actually exact. This suggests that for higher precision, the assumption that $\epsilon$ is small is violated and the Taylor series formulation no longer holds.
42 |
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/combat/list_of_terms.tex:
--------------------------------------------------------------------------------
1 | \section*{List of Combat Related Terms and Associated Values}
2 | \begin{enumerate}
3 | \item Combat Class: One of $[\texttt{melee, ranged, magic}]$
4 | \item Attack Type: One of $[\texttt{stab, slash, crush, ranged, magic}]$
5 | \item Combat Style: The name of the attack.
6 | \begin{enumerate}
7 | \item For the \texttt{melee} combat class: One of [\texttt{punch, kick, chop, hack, smash, block, pound, pummel, slash, lunge, jab, swipe, fend, spike, impale, reap, flick, lash, deflect, bash, focus, scorch}]
8 | \item For the \texttt{ranged} combat class: One of [\texttt{accurate, rapid, longrange, short fuse, medium fuse, long fuse, flare}]
9 | \item For the \texttt{magic} combat class: One of [\texttt{spell, spell (defensive), blaze, accurate, longrange}]. The latter two only apply to \texttt{Powered staves}.
10 | \end{enumerate}
11 | \item Attack Style:
12 | \begin{enumerate}
13 | \item For the \texttt{melee} combat class: One of $[\texttt{accurate, aggressive, defensive, controlled}]$
14 | \item For the \texttt{ranged} combat class: One of $[\texttt{accurate, rapid, longrange}]$
15 | \item For the \texttt{magic} combat class: One of [$\texttt{standard, defensive}]$
16 | \end{enumerate}
17 | \item Attack Speed: The number of ticks between attacks. Integer between 1 and 15.
18 | \item Attack Interval: The number of second between attacks. Real number between 0.6s and 9s.
19 | \item Attribute: When referring to an opponent/monster, their \texttt{attribute} is one of $[\texttt{Demon, Draconic, Fiery, Kalphite, Leafy, Penance, Shade, Undead, Vampyre, Xerician}]$. In addition, we expand this to also include properties like: $[\texttt{On slayer task, In wilderness}]$.
20 | \end{enumerate}
21 |
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/combat/optimal_training_order.tex:
--------------------------------------------------------------------------------
1 | \section{Dijkstra's algorithm}
2 | Any time the player is training combat, they have to also make a choice about what skill to train. The skill choices are attack, strength, ranged, magic, and defence. Hitpoints is automatically trained regardless of style, and prayer is not generally trained during combat (although it is totally possible). Furthermore, attack options that offer "shared xp" significantly complicate the model since it forces the problem space into xp (which exceeds 10 million) whereas without that only levels are needed (less than 100), as a result it will also be ignored.
3 |
4 | Let's assume a player in a standard loadout (using a dscim within the Nightmare Zone) starts at levels (attack=60, strength=60) and their goal is obtaining (99, 99). The player's first choice is between training to (61, 60) or (60, 61). Repeatedly asking that question all the way to (99, 99) gives the tree-like graph depicted in Fig.~\ref{fig:training_order60}.
5 |
6 |
7 | Since every level exponentially increases the amount of time it takes to train, training one skill results in diminishing returns. Shortest Path algorithms are specially designed to solve this problem, with Dijkstra's algorithm being able to compute exact solutions. The interplay between incremental boosts and longer training times produces optimal solutions like the one shown in Fig.~\ref{fig:training_order_sequence}. This is further illustrated in Fig.~\ref{fig:training_graph}.
8 |
9 | \begin{figure}
10 | \centering
11 | \includegraphics[width=0.5\linewidth]{img/combat/training_order60.png}
12 | \caption{
13 | A depiction of the choices the player has to make as they train their attack and strength skills from (60, 60) to (99, 99). Starting at the top, each tier represents a choice to train either attack (right-down) or strength (left-down).
14 | }
15 | \label{fig:training_order60}
16 | \end{figure}
17 |
18 | \begin{figure}
19 | \centering
20 | \includegraphics[width=\linewidth]{img/combat/training_order_sequence.png}
21 | \caption{
22 | The sequence of training strength (red) and attack (green) for a player both using potions and not. It is clear that starting with strength training is ideal, with the last levels all being attack.
23 | }
24 | \label{fig:training_order_sequence}
25 | \end{figure}
26 |
27 | \begin{figure}
28 | \centering
29 | \includegraphics[width=\linewidth]{img/combat/training_graph.png}
30 | \caption{
31 | The time taken to level up plotted against the number of levels the player has trained. Two bands clearly emerge which are associated with strength (top) and attack (bottom). The player initially trains strength (driving up the time to level) until about 15 levels are gained, at which point the minor improvement from attack out-competes the large amount of time to get the next strength level.
32 | }
33 | \label{fig:training_graph}
34 | \end{figure}
35 |
36 | The human player typically optimizes these choices heuristically, and so it is interesting to compare the optimal graph solution with other options. The table below compares different strategies, most notably the optimal solution is only a 0.5\% improvement over simply training strength to 99 then training attack. By contrast, maxing attack first increases training time by 20\%, since the max hit cannot increase. Most players intuitively understand that strength is much more important than attack.
37 |
38 | \begin{table}[h!]
39 | \centering
40 | \begin{tabular}{|l|c|c|c|}
41 | \hline
42 | \textbf{Strategy} & \textbf{Total Time (h)} & \textbf{Additional Time (h)} & \textbf{\% Improvement} \\
43 | \hline
44 | Inverted & 356.6 & 30.1 & 8.4 \\
45 | \hline
46 | $(1, 99) \to (99, 99)$ & 328.3 & 1.8 & 0.5 \\
47 | \hline
48 | $(99, 1) \to (99, 99)$ & 393.4 & 66.9 & 17 \\
49 | \hline
50 | \end{tabular}
51 | \caption{Comparison of different training orders}
52 | \label{table:1}
53 | \end{table}
54 |
55 |
56 | The main reason defence training has been omitted is that if defence is trained the player may unlock new armor. So the solution described in the Optimizing Player Equipment chapter is required. At each level, the optimal equipment is determined by set reduction and the experience rates are then calculated. In Fig.~\ref{fig:defence_training} the effect of equipment upgrades is shown.
57 |
58 | \begin{figure}
59 | \centering
60 | \includegraphics[width=\linewidth]{img/combat/defence_training.png}
61 | \caption{
62 | The optimal training order solution from level (1, 1) to (99, 99), while allowing for optimal equipment to be determined at each level. Green nodes indicate that a previously unseen/unused piece of equipment is now being used by the player. Blue nodes indicate that the player changed their gear to something they previously had. The consistent leftward tilt of the training order suggests that keeping your strength $\sim$10\% over your attack level is near-optimal.
63 | }
64 | \label{fig:defence_training}
65 | \end{figure}
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/general/experience_and_levels.tex:
--------------------------------------------------------------------------------
1 | The experience required to reach a level $L$ is given by,
2 | \begin{align}\label{eq:xp_given_level}
3 | \mathcal{L}^{-1}(L) &\equiv \left \lfloor \frac{1}{4} \sum_{l=1}^{L-1} \left \lfloor l + 300\cdot2^{l/7} \right \rfloor \right\rfloor\\
4 | &\approx \frac{1}{8}\left( L^2 - L + 600\frac{2^{L/7} - 2^{1/7}}{2^{1/7}-1}\right).
5 | \end{align}
6 | The level of a skill with $E$ experience is defined as:
7 | \begin{align}\label{eq:level_given_xp}
8 | \mathcal{L}(E).
9 | \end{align}
10 | No analytic form has been found for this equation, however it can be straightforwardly evaluated by numerically inverting Eq.~(\ref{eq:xp_given_level}) or by building lookup tables.
11 |
12 | The level equation itself is exponentially slow, and this effect extends to the overall time to max all skills. For example, one youtuber, WildMudKip provides total level and date stamps through their \href{https://www.youtube.com/watch?v=MiTp-06zJHk&list=PL4Ct8chrkvPgti4HYTZFo7FSfxlLlptbN&ab_channel=WildMudkip}{HCIM youtube series}, by scraping this data, Fig.~\ref{fig:maxing_time} now shows that the total level over time is also logarithmic.
13 |
14 |
15 | \begin{figure}
16 | \centering
17 | \includegraphics[width=\linewidth]{img/general/wildmudkip_maxing.png}
18 | \caption{
19 | Youtuber WildMudKip's hardcore ironman levels over time reveal an logarithmically slow progression. Near optimal play and consistent upload and play time are all reasonable assumptions.
20 | }
21 | \label{fig:maxing_time}
22 | \end{figure}
23 |
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/introduction.tex:
--------------------------------------------------------------------------------
1 | \textit{Runescape} (RS) is a popular \textit{Massively Multiplayer Online Role-Playing Game} (MMORPG) that was first publicly released on January 4'th, 2001 by the video game developer Jagex Limited. Ranked as the 5'th most popular MMORPG in 2020 by several sources, this game's unique mechanisms and game play make it still successful nearly 20 years after it's incarnation \cite{bestreamer:10_most_played_mmorpgs_of_2020, altarofgaming:top_6_most_popular_mmorpgs, thegamer:ranking_the_15_best_mmorpgs}.
2 | On the 20th of November 2012, a total overhaul to the game's combat system - an integral part of gameplay - caused a great divide among it's players. As a result, the game bifurcated into two versions: Runescape 3, and \textit{Old School Runescape} (OSRS). The latter was released on February 22, 2013 and reverted to the old mechanics. The relative player counts over time can be found in Ref.~\cite{misplacedme:relative_player_counts}. OSRS currently contains the majority of players. To limit the already-large scope, this text will only focus on that version.
3 |
4 | In typical role-playing fashion, the majority of game play centers around fighting monsters and bosses, training skills, completing quests, playing mini-games, and collecting items. This game is played over the course of months or years. In a few years, there will even be some players who have played for \emph{decades}. As the player base gained a more comprehensive understanding of the game, their mentality has generally shifted from one of discovery to one of \emph{efficiency}. Many tools have been created with the goal of improving player efficiency, optimizing game play, and maximizing success in difficult challenges. %A non-comprehensive list can be found in the \textcolor{red}{appendix [link]}.
5 |
6 | There are 23 skills that a player can train \cite{wiki:skills}. A player is rewarded experience for certain actions related to a given skill. For example, cutting an \texttt{Oak Tree} yields 37.5 experience per log chopped. 83 Experience is required to go from level 1 to level 2, while reaching the maximum level of 99 requires 13,034,431 total experience \cite{wiki:experience}. The experience required to level up increases exponentially - hence the drive for efficiency \cite{wiki:experience}. There are several combat skills that directly influence a player's fighting ability. Quests are often completed for the special items, new training methods, and experience rewards they provide. They have skill requirements and often make use of combat in defeating difficult bosses. And so even in this basic overview, the complexity of the interactions and relations between different actions a player can perform becomes apparent.
7 | % Combat is perhaps the most interesting aspect of the game and serves as a dominant focus of this text.
8 |
9 | \begin{figure}[h!]
10 | \centering
11 | \includegraphics[width=\linewidth]{img/general/skills_quest_player.png}
12 | \caption{
13 | Some relevant interfaces/images that play a central role in game play. The skill panel (left) shows the player's levels in the 23 skills along with their total level (Image slightly modified from Ref.~\cite{wiki:skills}). The combat skills, attack, strength, defence, ranged, prayer, magic, and health (in the middle column), are respectively outlined in red. The quest panel (middle) shows the player's quests that are completed, in progress, and not started (green, yellow, and red, respectively. Image from Ref.~\cite{wiki:quests}). A character that a player would control in a 3D world is shown on the right.
14 | }
15 | \label{fig:skills_quest_player}
16 | \end{figure}
17 |
18 | \newpage
19 | To understand player decisions and optimize them, we will be mathematically modeling the in-game mechanics. A surprising variety of mathematical concepts and techniques will be encountered. Additionally, algorithms derived from computer science are required to solve some of these problems. This serves as an exciting \textit{field} to explore, with some very interesting results and visuals. Some of the details require high level mathematical solutions/descriptions.
20 | \vspace{2em}
21 | \newline
22 | % This text accompanies an open-source codebase titled \href{https://github.com/Palfore/OSRSmath}{``OSRSmath''} that can be found on Github at \url{https://github.com/Palfore/OSRSmath}. In addition, there is a video series titled ``Optimizing Runescape'' that covers some of these solutions, and can be. Finally, a \href{https://discord.gg/4SXcKQh}{Discord Chat Room} exists for related discussions.
23 |
24 |
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/mining/mining.tex:
--------------------------------------------------------------------------------
1 |
2 |
3 | Mining focuses on collecting ores by extracting them from rocks with a given pickaxe. The main modifiers to experience are the type of pickaxe and the type of ore. Mining success rates are actually much harder to find than woodcutting for example. As a result calculating experience rates is much more difficult. Instead, in this section we look at the \href{https://oldschool.runescape.wiki/w/Motherlode_Mine}{Motherload Mine} which is a very common mining technique.
4 |
5 | This activity enhances mining by providing a chance to obtain \emph{Gold Nuggets} which can be used to purchase rewards like the \emph{Prospector Outfit} that increases experience per ore mined. Each piece costs a certain amount, and each piece provides an experience boost, with more costly pieces providing more bonuses. So the natural question here is what order should the four pieces be purchased. With only four pieces a brute force approach is sufficient here as Fig.~\ref{fig:pay_dirt} reveals the optimal order to be
6 | \begin{equation}
7 | \text{Jacket} \to \text{Legs} \to \text{Hat} \to \text{Boots},
8 | \end{equation}
9 | which is exactly the order of most expensive to least expensive items. The worst ordering is
10 | \begin{equation}
11 | \text{Boots} \to \text{Hat} \to \text{Legs} \to \text{Jacket},
12 | \end{equation}
13 | which is the reverse of the optimal solution. Another way to visualize this is shown in Fig.~\ref{fig:mining_order}.
14 |
15 |
16 | \begin{figure}
17 | \centering
18 | \includegraphics[width=\linewidth]{img/mining/varying_paydirt.100.png}
19 | \caption{
20 | A ranking of all possible orderings to obtain the full outfit. Notice that the x-axis here is the experience from the paydirt although this is fixed in game at 60, varying this parameter reveals that the order is very stable (rankings only change by 1 or 2). The order "JLHB" is the optimal, which "BHLJ" is the worst as it is the reverse order.
21 | }
22 | \label{fig:pay_dirt}
23 | \end{figure}
24 |
25 | \begin{figure}
26 | \centering
27 | \includegraphics[width=0.5\linewidth]{img/mining/optimal_order.pdf}
28 | \caption{
29 | Starting on the left side, each line represents a possible ordering of obtaining the full set. The thickness of each line represents its rank. Clearly starting with the jacket (3rd row) is optimal, whereas starting with the boots (1st row) is worst. Said another way (looking at the bottom row), getting the jacket last is the worst and getting the boots last is the best.
30 | }
31 | \label{fig:mining_order}
32 | \end{figure}
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/quests/quests.tex:
--------------------------------------------------------------------------------
1 | Quests are a massive part of playing the game with tons of content being unlocked by them. Moreover, their large experience rewards drive efficient players to empirically determine the \href{https://oldschool.runescape.wiki/w/Optimal_quest_guide#Quests}{optimal order of completing quests} to obtain any particular goal (most notably the \href{https://oldschool.runescape.wiki/w/Quest_point_cape}{Quest Point Cape}).
2 |
3 | The difficulty in optimization arises from the complex dependencies between the quests. To handle this, we can treat each quest as an abstract node. A node has two standard prerequisites: the skill level requirements and the quest requirements. The skill requirements are a property of the node itself, but the quest requirements form edges between these nodes. Since quests reward experience unlocks skill levels, the graph becomes a dynamic, directed acyclic graph (DAG).
4 |
5 | Other considerations like item requirements and combat (including bosses) further complicate this process and are not yet considered. Since item requirements can mostly be seen as level requirements, combat becomes the bigger focus. A player could define various constraints for all required combat (eg: $P_\text{win}>0.01$), but this would require modeling equipment progression etc. Although, it would be a major achievement to include all these effects for the purpose of solving the quest problem, for this initial work quests will only depend on skills and other quests.
6 |
7 | Quests can only depend on another quest in one direction and as a result they are naturally assigned tiers. For example, tier 0 quests have no quest dependencies, while tier 1 can only depend on Tier 0 quests (or no quests). Each tier depends exclusively on quests in lower tiers. This organizational hierarchy can be seen in Fig.~\ref{fig:quests_by_requirement}.
8 |
9 | The \href{https://osrsmath.palfore.com/}{Runescape Universe} is an interactive tool to explore the quest tree in both OSRS and RS3, created by this project to provide users with an interactive way to explore the dynamic, complex, and intertwined quest lines as shown in Fig.~\ref{fig:osrs_universe}. For example, the iconic quest \href{https://oldschool.runescape.wiki/w/Monkey_Madness_I}{Monkey Madness I} is shown in Fig.~\ref{fig:osrs_universe_zoom} to connect to a central network. In fact, all quests are connected to the large central island, except for isolated nodes (typically only 1 or 2 nodes). Only trivial quest islands existed until the \href{https://oldschool.runescape.wiki/w/Varlamore}{Varlamore continent} was released. This island is likely temporary since the same thing happened when the \href{https://oldschool.runescape.wiki/w/Great_Kourend}{Kourend continent} was released, but was later connected to the main island through \href{https://oldschool.runescape.wiki/w/Dragon_Slayer_II}{DSII}.
10 |
11 |
12 |
13 |
14 | \begin{figure}
15 | \centering
16 | \includegraphics[width=\linewidth]{img/quests/osrs_by_requirement.pdf}
17 | \caption{
18 | The OSRS quest tree, which organizes all quests into tiers, with higher tier quests depending exclusively on lower tier quests. With the release of \emph{Song of the Elves} in 2019, OSRS gained a 7th quest tier. By contrast RS3 has 11 tiers (Aftermath and Sliske's Endgame). Edges are colored by the quest tier they unlock. Increasing tiers diminish in size, although this is not required and stems from game design choices.
19 | }
20 | \label{fig:quests_by_requirement}
21 | \end{figure}
22 |
23 |
24 |
25 | \begin{figure}
26 | \centering
27 | \includegraphics[width=0.8\linewidth]{img/quests/universe.png}
28 | \caption{
29 | The Runescape Universe renders all quests and mini-quests as nodes in a graph. The quest prerequisites form edges between the nodes. Isolated islands form quest chains consisting of only one or two nodes. The colors here represent the \href{https://oldschool.runescape.wiki/w/Quests/Series}{quest series} and the size represents the official length of the quest. It is within this picture that nearly all the adventures of our player character are experienced.
30 | }
31 | \label{fig:osrs_universe}
32 | \end{figure}
33 |
34 |
35 |
36 |
37 | \begin{figure}
38 | \centering
39 | \includegraphics[width=0.8\linewidth]{img/quests/zoom.png}
40 | \caption{
41 | A closer view on the Gnome series, which highlights Monkey Madness II, detailing its information in a tooltip. The thick edges represent the direct connections to this quest. Another iconic quest, Desert Treasure I is also pictured. The physical proximity in the graph tends to represent their relatedness i.e. quests in the desert tend to be near each other.
42 | }
43 | \label{fig:osrs_universe_zoom}
44 | \end{figure}
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/title.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/docs/latex/tex/title.pdf
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/title.tex:
--------------------------------------------------------------------------------
1 | \documentclass[12pt,a4paper]{article}
2 | \newcommand{\HRule}[1]{\rule{\linewidth}{#1}}
3 |
4 | \author{Palfore}
5 | \title{
6 | \HRule{0.5pt}\\
7 | \LARGE \textbf{\uppercase{Mathematical Game Modeling and Optimization}}\\
8 | Optimizing Player Decisions in Old School Runescape\\
9 | \HRule{2pt}\\
10 | }
11 |
12 | \begin{document}
13 | \pagenumbering{Alph}
14 | \begin{titlepage}
15 | \maketitle
16 | \thispagestyle{empty}
17 | \end{titlepage}
18 | \pagenumbering{arabic}
19 | \end{document}
--------------------------------------------------------------------------------
/osrsmath/docs/latex/tex/woodcutting/woodcutting.tex:
--------------------------------------------------------------------------------
1 |
2 |
3 | Woodcutting focuses on collecting logs by chopping them with a given axe. The main modifiers to experience are the type of axe and the type of tree. In Fig.~\ref{fig:woodcutting_landscape} you can see an experience landscape that shows the experience rate per hour based on the tree (by level, eg: 15 is oak) and wooductting level. For this section, a small dataset was collected to measure various tree chop rates at a few levels. The rates are interpolated to work for any level.
4 |
5 |
6 | Each tree requires data to be collected at two points and a linear interpolation can be used to determine the rate at any level. The sample was collected on two accounts at level 45 and 77 woodcutting. Since trees above 45 cannot be cut, they represented extrapolated values. Since the highest level that can analyzed by this data collection is 45, parts of the landscape aren't possible (eg: chopping Oak at level 1).
7 |
8 | \begin{figure}
9 | \centering
10 | \includegraphics[width=\linewidth]{img/woodcutting/experience.pdf}
11 | \caption{
12 | The experience levels for \emph{Teak Trees} in red are exactly known and not estimated by a sample. The portion in green represents extrapolations out side of the dataset (due to the 45 woodcutting limitation). As a result the extrapolations near $L=50$ are misleading.
13 | }
14 | \label{fig:woodcutting_landscape}
15 | \end{figure}
16 |
17 |
18 | For more details, you can watch the \href{https://www.youtube.com/watch?v=vYPLkFTDe5Y&t=39s&ab_channel=Palfore}{Optimizing Runescape Woodcutting Video}. Furthermore, the wiki team has recently provided a complete and comprehensive set of values in the \href{https://oldschool.runescape.wiki/w/Pay-to-play_Woodcutting_training\#Theoretical_experience_rates}{Theoretical Woodcutting XP Rates} page which now supersedes this work.
19 |
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_I/Accuracy.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_I/Accuracy.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_I/accuracy.py:
--------------------------------------------------------------------------------
1 | from osrsmath.skills.combat.accuracy import accuracy
2 | from matplotlib import cm
3 | import matplotlib.pyplot as plt
4 | import osrsmath.config as config
5 | import numpy as np
6 | import sys
7 | import os
8 |
9 | if __name__ == '__main__':
10 | showing = len(sys.argv) >= 2 and sys.argv[1] == 'show'
11 |
12 | a = range(1000)
13 | d = range(1000)
14 | a, d = np.meshgrid(a, d)
15 | A = np.vectorize(accuracy)(a, d)
16 |
17 | fig, ax = config.get_figure(-168, 25, scale=5 if showing else 10)
18 | plt.xlabel("$A_{max}$", fontsize=15)
19 | plt.ylabel("$D_{max}$", fontsize=15)
20 | ax.set_zlabel("Accuracy", fontsize=15, rotation=90)
21 | surf = ax.plot_surface(a, d, A, cmap=cm.coolwarm)
22 |
23 |
24 | ax.plot([1000], [1000], [1.01])
25 | ax.plot(range(1000), range(1000), [accuracy(x, x) for x in range(1000)], linewidth=2, c='black', zorder=3)
26 |
27 | if showing:
28 | plt.show()
29 | else:
30 | file_name = "Accuracy"
31 | plt.savefig(f"{file_name}.pdf")
32 | os.system(f"pdfcrop {file_name}.pdf")
33 | os.rename(f"{file_name}-crop.pdf", f"{file_name}.pdf")
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/average_damage.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_II/average_damage.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/average_damage.py:
--------------------------------------------------------------------------------
1 | import osrsmath.combat.damage as damage
2 | from matplotlib import cm
3 | import matplotlib.pyplot as plt
4 | import osrsmath.config as config
5 | import numpy as np
6 | import sys
7 | import os
8 |
9 | if __name__ == '__main__':
10 | showing = len(sys.argv) >= 2 and sys.argv[1] == 'show'
11 | fig, ax = config.get_figure(-124, 23, scale=5 if showing else 10)
12 | plt.xlabel("$M$", fontsize=15)
13 | plt.ylabel("$h$", fontsize=15)
14 | ax.set_zlabel("Average Damage", fontsize=15, rotation=90)
15 |
16 | h, M = 100, 100
17 | y, x = np.meshgrid(range(h), range(M))
18 | z = np.vectorize(damage.average)(y, x)
19 | surf = ax.plot_surface(x, y, z, cmap=cm.coolwarm)
20 |
21 | xs = range(min(h, M))
22 | ax.plot(xs, xs, [damage.average(x, x) for x in xs], linewidth=2, c='black', zorder=3)
23 |
24 | if showing:
25 | plt.show()
26 | else:
27 | file_name = "average_damage"
28 | plt.savefig(f"{file_name}.pdf")
29 | os.system(f"pdfcrop {file_name}.pdf")
30 | os.rename(f"{file_name}-crop.pdf", f"{file_name}.pdf")
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/best_model.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_II/best_model.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/best_model.py:
--------------------------------------------------------------------------------
1 | from osrsmath.results.part_II.colors import colors
2 | from osrsmath.results.part_II.generate_simulation import load_dataset
3 | import osrsmath.combat.successful_hits as sh
4 |
5 | import matplotlib as mpl
6 | import matplotlib.colors as clrs
7 | import matplotlib.pyplot as plt
8 | import numpy as np
9 | import operator
10 | import sys
11 | import inspect
12 | import os
13 |
14 | def draw(ax, to_print, colorbar=True, yaxis=True):
15 | used_colors = colors#{n: c for n, c in colors.items() if n in to_print}
16 | best_model = np.array([np.array([
17 | list(used_colors).index(
18 | min({ # https://stackoverflow.com/questions/268272/getting-key-with-maximum-value-in-dictionary
19 | n: abs(1 - classes[n]().hinv(0.5 if n == "Recursive" else 0, h, m) / sim[str(h)][str(m)] ) for n in to_print
20 | }.items(), key=operator.itemgetter(1))[0]
21 | )
22 | for m in max_hits]) for h in healths])
23 |
24 | cmap = mpl.colors.ListedColormap(list(used_colors.values()))
25 | boundaries = [-0.5] + [list(used_colors).index(c) + 0.5 for c in used_colors]
26 | norm = clrs.BoundaryNorm(boundaries, cmap.N, clip=True)
27 | return ax.imshow(best_model, aspect='auto', origin='lower', cmap=cmap, norm=norm, interpolation='none')
28 |
29 | if __name__ == '__main__':
30 | m_min, m_max = (1, 110)
31 | h_min, h_max = (1, 255)
32 | max_hits = np.array(range(m_min, m_max+1))
33 | healths = np.array(range(h_min, h_max+1))
34 | Ms, Hs = np.meshgrid(max_hits, healths)
35 |
36 | classes = {name: cl for name, cl in inspect.getmembers(sh, inspect.isclass)}
37 | sim = load_dataset(N=100_000)
38 |
39 | fig, axes = plt.subplots(nrows=1, ncols=3)
40 | scale=10
41 | fig.set_size_inches((1920/1080*scale, scale/2))
42 | ax1, ax2, ax3 = axes.flat
43 | ax2.set_yticklabels([])
44 | ax2.tick_params(axis='y', which='both', left=False, right=False, labelbottom=False)
45 | ax3.set_yticklabels([])
46 | ax3.tick_params(axis='y', which='both', left=False, right=False, labelbottom=False)
47 | ax1.set_ylabel("$h_0$", fontsize=25)
48 | ax2.set_xlabel("M", fontsize=25)
49 | ax1.tick_params(axis='y', labelsize=18)
50 | ax1.tick_params(axis='x', labelsize=18)
51 | ax2.tick_params(axis='x', labelsize=18)
52 | ax3.tick_params(axis='x', labelsize=18)
53 |
54 | im = draw(ax3, ["Crude", "Average", "Recursive", "MarkovChainApprox", "MarkovChain"], colorbar=False, yaxis=False)
55 | draw(ax2, ["Crude", "Average", "Recursive", "MarkovChainApprox"], colorbar=False, yaxis=False)
56 | draw(ax1, ["Crude", "Average", "Recursive", ], colorbar=False)
57 |
58 | cbar_ax = fig.add_axes([0.12, 0.0, .78, 0.03])
59 | cb = fig.colorbar(im, cax=cbar_ax, orientation='horizontal')
60 | cb.set_ticks([list(colors).index(c) for c in colors])
61 | cb.set_ticklabels([k.replace('MarkovChain', 'MC') for k in colors.keys()])
62 | cb.ax.tick_params(labelsize=25)
63 | fig.subplots_adjust(wspace=0.02, bottom=0.2)
64 |
65 | showing = len(sys.argv) >= 2 and sys.argv[1] == 'show'
66 | if showing:
67 | plt.show()
68 | else:
69 | file_name = "best_model"
70 | plt.savefig(f"{file_name}.pdf", bbox_inches='tight')
71 | os.system(f"pdfcrop {file_name}.pdf")
72 | os.rename(f"{file_name}-crop.pdf", f"{file_name}.pdf")
73 | plt.close()
74 |
75 |
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/colors.py:
--------------------------------------------------------------------------------
1 | colors = {
2 | "Crude": "red",
3 | "Average": "orange",
4 | "Recursive": "green",
5 | "RecursiveApproximation": "lime",
6 | "MarkovChain": "blue",
7 | "MarkovChainApproximation": "cyan",
8 | }
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/comparison.py:
--------------------------------------------------------------------------------
1 | from osrsmath.results.part_II.colors import colors
2 | from osrsmath.combat.successful_hits import *
3 | from osrsmath.results.part_II.generate_simulation import load_dataset
4 | from pprint import pprint
5 | from mpl_toolkits.mplot3d import Axes3D
6 | import matplotlib.pyplot as plt
7 | import numpy as np
8 | import sys
9 | import os
10 | import osrsmath.config as config
11 |
12 | if __name__ == '__main__':
13 | showing = len(sys.argv) >= 2 and sys.argv[1] == 'show'
14 | fig, ax = config.get_figure(38, 17, scale=3 if showing else 10)
15 |
16 | m_min, m_max = (1, 110)
17 | h_min, h_max = (1, 255)
18 | max_hits = np.array(range(m_min, m_max+1))
19 | healths = np.array(range(h_min, h_max+1))
20 | Ms, Hs = np.meshgrid(max_hits, healths)
21 | sim = load_dataset(N=100_000)
22 |
23 | def plot_error(label, inverse):
24 | """ inverse: hinv(h, m) """
25 | def err(a, b):
26 | # return abs(a - b)
27 | return abs(1 - a /b)*100
28 | print(label)
29 | Z = np.array([np.array([err(inverse(h, m), sim[str(h)][str(m)]) for m in max_hits]) for h in healths])
30 | surf = ax.plot_wireframe(Ms, Hs, Z, color=colors[label], linewidth=2.3, label=f"{label}")
31 | return {label: (np.average(Z), np.std(Z), np.max(Z), np.min(Z))}
32 |
33 | values = {}
34 | for method in Model.__subclasses__():
35 | if method.__name__ == 'Simulation':
36 | continue
37 | values.update(plot_error(method.__name__, lambda h, m: method().turns_to_kill(h, m)))
38 |
39 | print(R"\begin{table}[h]")
40 | print('\t' + R"\centering")
41 | print('\t' + R"\begin{tabular}{ l | c c c c }")
42 | print('\t\t' + R"Model & Average & Standard Deviation & Maximum & Minimum \\")
43 | print('\t\t' + R"\hline\hline")
44 | for label, (avg, stdd, M, m) in values.items():
45 | print('\t\t' Rf'{label} & {avg:.2f} & {stdd:.2f} & {M:.2f} & {m:.2e} \\')
46 | print('\t' + R"\end{tabular}")
47 | print('\t' + R"\caption{Error statistics for various models.}")
48 | print('\t' + R"\label{table:model_comp_stats}")
49 | print(R"\end{table}")
50 | # exit()
51 |
52 | ax.tick_params(axis='z', labelsize=12)
53 | ax.tick_params(axis='y', labelsize=12)
54 | ax.tick_params(axis='x', labelsize=12)
55 | ax.set_zlabel("Percent Error", fontsize=16, labelpad=20)
56 | plt.xlabel("Max Hit", fontsize=16, labelpad=20)
57 | plt.ylabel("Initial Health", fontsize=16, labelpad=20)
58 | leg = plt.legend(loc=(0.6, 0.6), fancybox=True, fontsize=16, markerscale=5)
59 | for legobj in leg.legendHandles:
60 | legobj.set_linewidth(4)
61 |
62 |
63 | if showing:
64 | plt.show()
65 | else:
66 | from pathlib import Path
67 | file_name = str(Path(__file__).parent/'errors')
68 | plt.savefig(f"{file_name}.png")
69 | os.system(f"convert {file_name}.png -trim {file_name}.png")
70 | # plt.savefig(f"{file_name}.pdf")
71 | # os.system(f"pdfcrop {file_name}.pdf")
72 | # os.rename(f"{file_name}-crop.pdf", f"{file_name}.pdf")
73 |
74 |
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/errors.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_II/errors.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/errors.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_II/errors.png
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/generate_simulation.py:
--------------------------------------------------------------------------------
1 | """ All this file does, is evaluate the simulation model in a given range of max hits and starting healths.
2 | It also stores the results in a file, so that it can be quickly loaded.
3 | Otherwise re-evaluating them can take hours or days. """
4 |
5 | from multiprocessing import Pool
6 | import inspect
7 | import json
8 | import os
9 | import osrsmath.config as config
10 | from osrsmath.combat.successful_hits import Simulation
11 |
12 | ## Multi-processing boiler plate, that allows for lambda's
13 | _func = None
14 | def worker_init(func):
15 | global _func
16 | _func = func
17 | def worker(x):
18 | return _func(x)
19 | def xmap(func, iterable, processes=None):
20 | with Pool(processes, initializer=worker_init, initargs=(func,)) as p:
21 | return p.map(worker, iterable)
22 |
23 | def create_dataset(file_path, N, max_hits, healths, final_health=0):
24 | print("Creating Dataset")
25 | simulation = Simulation(N)
26 | dataset = {
27 | "N": N,
28 | "source": inspect.getsource(Simulation(N).hinv),
29 | "data": {
30 | str(h): {
31 | str(m): hinv for m, hinv in xmap(lambda m: (str(m), simulation.hinv(final_health, h, m)), max_hits, processes=12)
32 | } for h in healths
33 | }
34 | }
35 | print("Saving Dataset")
36 | with open(file_path, 'w') as f:
37 | json.dump(dataset, f)
38 |
39 | def load_dataset(N, max_hits=None, healths=None, final_health=0):
40 | if final_health == 0:
41 | file_path = os.path.join(config.DATA_PATH, f"simulations/simulation.{N}.dat")
42 | else:
43 | file_path = os.path.join(config.DATA_PATH, f"simulations/simulation.{N}.{final_health}.dat")
44 |
45 | if not os.path.exists(file_path):
46 | if max_hits is None or healths is None:
47 | raise ValueError(f"The dataset at {file_path} needs to be created, please supply the max_hits and healths.")
48 | create_dataset(file_path, N, max_hits, healths)
49 | return json.load(open(file_path))['data']
50 |
51 | if __name__ == '__main__':
52 | N = 100_000
53 | m_min, m_max = (1, 110)
54 | h_min, h_max = (1, 255)
55 | x = np.array(range(m_min, m_max+1))
56 | y = np.array(range(h_min, h_max+1))
57 | create_dataset(N, x, y)
58 |
59 |
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/models/Average.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_II/models/Average.png
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/models/Crude.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_II/models/Crude.png
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/models/MarkovChain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_II/models/MarkovChain.png
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/models/MarkovChainApproximation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_II/models/MarkovChainApproximation.png
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/models/Recursive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_II/models/Recursive.png
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/models/RecursiveApproximation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_II/models/RecursiveApproximation.png
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/models/generate.py:
--------------------------------------------------------------------------------
1 | from osrsmath.results.part_II.colors import colors
2 | from osrsmath.combat.successful_hits import *
3 | from osrsmath.results.part_II.generate_simulation import load_dataset
4 | from pprint import pprint
5 | from mpl_toolkits.mplot3d import Axes3D
6 | import matplotlib.pyplot as plt
7 | import numpy as np
8 | import sys
9 | import os
10 | import osrsmath.config as config
11 |
12 | if __name__ == '__main__':
13 |
14 | showing = len(sys.argv) >= 2 and sys.argv[1] == 'show'
15 |
16 | m_min, m_max = (1, 110)
17 | h_min, h_max = (1, 255)
18 | max_hits = np.array(range(m_min, m_max+1))
19 | healths = np.array(range(h_min, h_max+1))
20 | Ms, Hs = np.meshgrid(max_hits, healths)
21 | sim = load_dataset(N=100_000)
22 |
23 | def plot_error(label, inverse):
24 | """ inverse: hinv(h, m) """
25 | def err(a, b):
26 | # return abs(a - b)
27 | return abs(1 - a /b)*100
28 | print(label)
29 | Z = np.array([np.array([err(inverse(h, m), sim[str(h)][str(m)]) for m in max_hits]) for h in healths])
30 | surf = ax.plot_wireframe(Ms, Hs, Z, color=colors[label], linewidth=1, label=f"{label}")
31 | return {label: (np.average(Z), np.std(Z), np.max(Z), np.min(Z))}
32 |
33 | for method in Model.__subclasses__():
34 | if method.__name__ == 'Simulation':
35 | continue
36 |
37 | fig, ax = config.get_figure(33, 36, scale=3 if showing else 10)
38 | plot_error(method.__name__, lambda h, m: method().turns_to_kill(h, m))
39 |
40 | ax.tick_params(axis='z', labelsize=12)
41 | ax.tick_params(axis='y', labelsize=12)
42 | ax.tick_params(axis='x', labelsize=12)
43 | ax.set_zlabel("Percent Error", fontsize=16, labelpad=20)
44 | plt.xlabel("Max Hit", fontsize=16, labelpad=20)
45 | plt.ylabel("Initial Health", fontsize=16, labelpad=20)
46 |
47 | if showing:
48 | plt.show()
49 | else:
50 | from pathlib import Path
51 | file_name = str(Path(__file__).parent/method.__name__)
52 | plt.savefig(f"{file_name}.png")
53 | os.system(f"convert {file_name}.png -trim {file_name}.png")
54 | # plt.savefig(f"{file_name}.pdf")
55 | # os.system(f"pdfcrop {file_name}.pdf")
56 | # os.rename(f"{file_name}-crop.pdf", f"{file_name}.pdf")
57 |
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/turns_to_kill.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_II/turns_to_kill.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/turns_to_kill.py:
--------------------------------------------------------------------------------
1 | from osrsmath.combat.successful_hits import *
2 | from matplotlib import cm
3 | import matplotlib.pyplot as plt
4 | import osrsmath.config as config
5 | import numpy as np
6 | import sys
7 | import os
8 |
9 | def plot(m_bounds, h_bounds):
10 | m_min, m_max = m_bounds
11 | h_min, h_max = h_bounds
12 | max_hits = np.array(range(m_min, m_max+1))
13 | healths = np.array(range(h_min, h_max+1))
14 | Ms, Hs = np.meshgrid(max_hits, healths)
15 | fig, ax = config.get_figure(50, 18, scale=5 if showing else 10)
16 | plt.xlabel("$h_0$", fontsize=25, labelpad=20)
17 | plt.ylabel("$M$", fontsize=25, labelpad=20)
18 | ax.set_zlabel("Turns to kill", fontsize=25, rotation=90, labelpad=20)
19 | ax.tick_params(axis='z', labelsize=18)
20 | ax.tick_params(axis='y', labelsize=18)
21 | ax.tick_params(axis='x', labelsize=18)
22 |
23 | A = np.vectorize(lambda m, h: MarkovChain().turns_to_kill(m, h))(Hs, Ms)
24 | surf = ax.plot_surface(Hs, Ms, A, cmap=cm.hot)
25 |
26 | A = np.vectorize(lambda m, h: Crude().turns_to_kill(m, h))(Hs, Ms)
27 | surf = ax.plot_surface(Hs, Ms, A, cmap=cm.cool)
28 | return plt
29 |
30 | if __name__ == '__main__':
31 | showing = len(sys.argv) >= 2 and sys.argv[1] == 'show'
32 | if showing:
33 | plot(m_bounds=(1, 110), h_bounds=(1, 250)).show()
34 | plot(m_bounds=(20, 110), h_bounds=(1, 110)).show()
35 | else:
36 | plot(m_bounds=(1, 110), h_bounds=(1, 250))
37 | file_name = "turns_to_kill"
38 | plt.savefig(f"{file_name}.pdf")
39 | os.system(f"pdfcrop {file_name}.pdf")
40 | os.rename(f"{file_name}-crop.pdf", f"{file_name}.pdf")
41 |
42 | plot(m_bounds=(20, 110), h_bounds=(1, 110))
43 | file_name = "turns_to_kill_zoom"
44 | plt.savefig(f"{file_name}.pdf")
45 | os.system(f"pdfcrop {file_name}.pdf")
46 | os.rename(f"{file_name}-crop.pdf", f"{file_name}.pdf")
47 |
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_II/turns_to_kill_zoom.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_II/turns_to_kill_zoom.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_III/big_tree.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_III/big_tree.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_III/optimize/backup.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_III/optimize/backup.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_III/optimize/costs.py:
--------------------------------------------------------------------------------
1 | # from jsoncomment import JsonComment
2 | # from osrsmath.apps.optimize import get_sets, get_best_set
3 | # from osrsmath.combat.fighter import get_equipment_data
4 | # from osrsmath.combat.experience import combat_level
5 | # from osrsmath.combat.monsters import Monster
6 | # from osrsmath.combat.boosts import BoostingSchemes
7 | # from pprint import pprint
8 | # import sys
9 | # import os
10 |
11 | # costs = { # Manually obtained on 2020-03-24, from wiki
12 | # 'Gadderhammer': 1_300,
13 | # 'Spiked manacles': 1_170_000,
14 | # 'Regen bracelet': 2_279_005,
15 | # 'Fremennik kilk': 5_332_258,
16 | # 'Amulet of torture': 17_054_112,
17 | # 'Brimstone ring': 4_106_804,
18 | # 'Warrior ring (i)': 42_983,
19 | # 'Black scimitar': 1_435,
20 | # 'Mithril scimitar': 392,
21 | # 'Adamant scimitar': 1_338,
22 | # 'Rune Gloves': 6_500,
23 | # 'Brine sabre': 149_403,
24 | # 'Barrows gloves': 100_000,
25 | # 'Berserker helm': 44_264,
26 | # 'Granite hammer': 831_247,
27 | # 'Obsidian platebody': 1_017_874,
28 | # 'Dragon Boots': 302_179,
29 | # 'Warrior helm': 41_863,
30 | # 'Obsidian platelegs': 821_706,
31 | # 'Berserker ring (i)': 2_804_443,
32 | # 'Dragon scimitar': 59_568,
33 | # 'Bandos chestplate': 20_353_605,
34 | # 'Neitiznot faceguard': 27_312_230 + 51_563,
35 | # 'Bandos tassets': 29_438_824,
36 | # 'Avernic defender': 83_636_792,
37 | # 'Abyssal whip': 2_541_568,
38 | # 'Primordial boots': 32_007_307,
39 | # 'Ferocious gloves': 6_202_804,
40 | # 'Blade of saeldor': 137_764_117,
41 | # }
42 |
43 | # if __name__ == '__main__':
44 | # # Retrieve Data
45 | # EQD = get_equipment_data()
46 | # parser = JsonComment()
47 | # data = parser.loadf("settings.json")
48 |
49 | # player_stats = data['player_stats']
50 | # defenders = {}
51 | # for name, (search_type, value) in data['defenders'].items():
52 | # if search_type == 'id':
53 | # defenders[name] = Monster.from_id(value)
54 | # elif search_type == 'name':
55 | # defenders[name] = Monster.from_name(value)
56 | # else:
57 | # raise ValueError(f'The search type must be either "id" or "name", not {search_type}')
58 | # ignore = data['ignore']
59 | # adjustments = data['adjustments']
60 |
61 | # graph = []
62 | # for i in [1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 99]:
63 | # player_stats.update({
64 | # 'attack': i,
65 | # 'strength': i,
66 | # 'defence': i,
67 | # })
68 | # player_stats.update({'cmb': combat_level(player_stats)})
69 | # sets = get_sets(data['training_skill'], defenders, player_stats, ignore, adjustments, EQD)
70 | # sets = [{ slot: eq for slot, eq in s if eq is not None} for s in sets]
71 | # print(f"There are {len(sets)} sets.")
72 | # s, xp, stance = best = get_best_set(player_stats, 'attack', lambda p: BoostingSchemes(p).overload(), defenders, sets)
73 |
74 | # cost = sum(costs.get(e, 0) for s, e in s.items()) / 1_000_000
75 | # graph.append({'level': i, 'xp': xp, 'cost': cost, 'xp/cost': xp/cost})
76 | # pprint(s)
77 | # print(i, xp, cost)
78 |
79 | # import matplotlib.pyplot as plt
80 | # plt.plot([c['level'] for c in graph], [c['xp/cost'] for c in graph], linewidth=5)
81 | # plt.xlabel('Level', fontsize=15)
82 | # plt.ylabel('Gold Efficiency [Exp Rate / Million GP]', fontsize=15)
83 | # plt.gca().tick_params(axis='both', labelsize=12)
84 | # plt.tight_layout()
85 |
86 | # if len(sys.argv) == 2 and sys.argv[1] == 'show':
87 | # plt.show()
88 | # else:
89 | # file_name = 'gold_efficiency'
90 | # plt.savefig(f"{file_name}.pdf")
91 | # os.system(f"pdfcrop {file_name}.pdf")
92 | # os.rename(f"{file_name}-crop.pdf", f"{file_name}.pdf")
93 |
94 |
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_III/optimize/gold_efficiency.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_III/optimize/gold_efficiency.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_III/optimize/settings.json:
--------------------------------------------------------------------------------
1 | /* This is the data file that the program will read.
2 | There are several things here:
3 | defenders:
4 | The set of opponents you will be fighting. It is best to do this by id since
5 | multiple opponents may have the same, but different stats. You can search by id here:
6 | ADD LINK!!!
7 | If you want to specify by name, its done so in a very similar format:
8 | arbitrary_label_for_your_reference: ["name", "Spider"]
9 | player_stats:
10 | You can specify as much or as few as you want. If it needs to know something
11 | like "can you wear a dragon pickaxe", it will ask you for your mining level.
12 | ignore:
13 | Some equipment in the cannot actually be wore in the main game, this lets you exclude those.
14 | Additionally, this considers EVERY equipment in the game. It's possible that you can't afford
15 | something, or don't want to get it (Fighter torso). The best way to do this is to run the algorithm,
16 | see if it spits out something you don't want, ignore it, and repeat.
17 | adjustments
18 | Some of the equipment data used is incorrectly recorded, or is hidden behind artificial quest requirements.
19 | Those are accounted for here. In addition, instead of ignoring something like barrows gloves, maybe you will
20 | get them when you have 60 combat stats, you can add this here. It is important that you add your particular
21 | ignores at the END of the list, so that it overwrites any of the other set adjustments.
22 |
23 | If you see/know about exceptions (things that should be ignored, or be adjusted) then please let me know.
24 | */
25 | {
26 | "defenders": {
27 | "Count Draynor": ["id", 6332],
28 | "Count Draynor2": ["id", 6332],
29 | },
30 | "player_stats": {
31 | "attack": 99,
32 | "strength": 99,
33 | "defence": 99,
34 | "hitpoints": 99,
35 | "ranged":99,
36 | "magic": 99,
37 | "prayer": 99,
38 | "slayer": 45,
39 | "mining":99,
40 | "woodcutting": 99,
41 | "thieving": 1,
42 | "agility": 50,
43 | "fishing": 99,
44 | },
45 | "ignore": [
46 | // https://oldschool.runescape.wiki/w/Spear_(Last_Man_Standing)
47 | "Spear",
48 | "Corrupted halberd (perfected)", "Crystal halberd (perfected)",
49 | "Corrupted halberd (attuned)", "Crystal halberd (attuned)",
50 | "Corrupted halberd (basic)", "Crystal halberd (basic)",
51 | "Crystal axe (inactive)",
52 | "Crystal sceptre",
53 | "Starter sword",
54 |
55 | ////// ADD THINGS YOU DO NOT WANT TO CONSIDER BELOW THIS LINE!
56 | "Infernal max cape", "Fire max cape", "Ardougne max cape", "Infernal cape",
57 | ],
58 | "adjustments": {
59 | // Not 30 https://oldschool.runescape.wiki/w/Gadderhammer
60 | "Gadderhammer": {"attack": 1},
61 |
62 | "Fire battlestaff": {"attack": 30, "magic": 30},
63 | "Water battlestaff": {"attack": 30, "magic": 30},
64 | "Air battlestaff": {"attack": 30, "magic": 30},
65 | "Earth battlestaff": {"attack": 30, "magic": 30},
66 | "Battlestaff": {"attack": 30, "magic": 30},
67 |
68 | "Ivandis flail": {"attack": 40, "slayer": 38, "strength": 40, "magic": 33},
69 |
70 | // Typo: payer, is this a bug in-game?
71 | "3rd age druidic staff": {"prayer": 65, "attack": 65},
72 |
73 | "Maple blackjack": {"thieving": 30},
74 | "Maple blackjack(o)": {"attack": 30, "thieving": 30},
75 | "Maple blackjack(d)": {"defence": 30, "thieving": 30},
76 |
77 | "Western banner 4": {"ranged": 70, "magic": 64, "cmb": 100},
78 | "Western banner 3": {"ranged": 70, "magic": 64, "attack": 42, "defence": 42, "hitpoints": 42, "prayer": 22, "strength": 42, "slayer": 93},
79 | "Western banner 2": {"ranged": 30, "cmb": 70},
80 | "Wilderness sword 4": {"magic": 96, "slayer": 83},
81 | "Wilderness sword 3": {"magic": 66, "slayer": 68},
82 | "Wilderness sword 2": {"magic": 60, "slayer": 50},
83 |
84 | // Need DT and https://forum.tip.it/topic/79597-desert-treasure-lowest-possible-level/page/2/
85 | "Shadow sword": {"attack": 30, "strength": 30, "magic": 51, "ranged": 42},
86 |
87 | // Need DS2
88 | "Mythical cape": {"magic": 75, "hitpoints": 50, "prayer": 42, "strength": 50, "cmb": 85, "slayer": 18, "ranged": 30},
89 |
90 | // RFD items are not properly accounted for
91 | "Spork": {"attack": 10},
92 | "Frying pan": {"attack": 20},
93 | "Meat tenderiser": {"attack": 46, "strength": 47, "defence": 41},
94 | "Cleaver": {"attack": 46, "strength": 47, "defence": 41},
95 | "Spatula": {"attack": 10},
96 | "Skewer": {"attack": 30},
97 | "Rolling pin": {"attack": 40, "defence": 41},
98 | "Katana": {"attack": 40},
99 | // There might other reqs for these gloves
100 | "Adamant Gloves": {"defence": 13},
101 | "Rune gloves": {"defence": 31},
102 | "Dragon gloves": {"defence": 41},
103 | "Barrows gloves": {"attack": 46, "strength": 47, "defence": 41},
104 | // https://www.reddit.com/r/2007scape/comments/4gbhzd/barrows_gloves_at_52_cmb/
105 | // http://i.imgur.com/RXvHBVS.png
106 |
107 | ////// ADD ADJUSTMENTS BELOW THIS LINE!
108 | }
109 | }
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_III/optimize/weapon_comparison.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_III/optimize/weapon_comparison.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_III/optimize/weapon_comparison.py:
--------------------------------------------------------------------------------
1 | # from collections import defaultdict
2 | # from osrsmath.apps.optimize import get_sets, eval_set, load
3 | # from osrsmath.combat.experience import combat_level
4 | # from osrsmath.combat.boosts import BoostingSchemes, Prayers, Potions
5 | # from pprint import pprint
6 | # import matplotlib.pyplot as plt
7 | # import sys
8 | # import os
9 |
10 | # if __name__ == '__main__':
11 | # player_stats, defenders, ignore, adjustments = config = load("settings.json")
12 | # player_stats.update({
13 | # 'attack': 50,
14 | # 'strength': 50,
15 | # 'defence': 50,
16 | # })
17 | # player_stats.update({'cmb': combat_level(player_stats)})
18 | # sets = get_sets(*config)
19 |
20 | # graph = defaultdict(list)
21 | # for s in sets:
22 | # _, xp, stance = eval_set(
23 | # player_stats, 'attack',
24 | # lambda p: BoostingSchemes(p, Prayers.none).constant(Potions.overload),
25 | # defenders, s
26 | # )
27 | # weapon = s['weapon'] if 'weapon' in s else s['2h']
28 | # graph[weapon].append(xp)
29 |
30 | # averages = {weapon: sum(xps)/len(xps) / 1_000 for weapon, xps in graph.items()}
31 | # averages = {k: v for k, v in sorted(averages.items(), key=lambda x: x[1])}
32 | # dmaxs = {weapon: max(xps) / 1_000 - averages[weapon] for weapon, xps in graph.items()}
33 | # dmins = {weapon: averages[weapon] - min(xps) / 1_000 for weapon, xps in graph.items()}
34 |
35 |
36 | # plt.bar(list(averages.keys()), list(averages.values()), yerr=[list(dmaxs.values()), list(dmins.values())], capsize=10)
37 | # plt.xlabel('Weapon', fontsize=15)
38 | # plt.ylabel('Average Exp Rate', fontsize=15)
39 | # plt.gca().tick_params(axis='both', labelsize=12)
40 | # plt.gca().set_xticklabels(list(averages.keys()), rotation=45, horizontalalignment ="right")
41 | # plt.tight_layout()
42 |
43 | # plt.ylim(min(list(averages.values())) - 5, max(list(averages.values())) + 5)
44 | # if len(sys.argv) == 2 and sys.argv[1] == 'show':
45 | # plt.show()
46 | # else:
47 | # file_name = 'weapon_comparison'
48 | # plt.savefig(f"{file_name}.pdf")
49 | # os.system(f"pdfcrop {file_name}.pdf")
50 | # os.rename(f"{file_name}-crop.pdf", f"{file_name}.pdf")
51 |
52 |
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_III/recur_(1, 1, 1).pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_III/recur_(1, 1, 1).pdf
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_III/tree.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_III/tree.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/combat/old/part_III/tree_bz_dagger_vs_dscim.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/combat/old/part_III/tree_bz_dagger_vs_dscim.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/firemaking/policies.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/firemaking/policies.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/firemaking/profit.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/firemaking/profit.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/firemaking/summary.out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/firemaking/summary.out
--------------------------------------------------------------------------------
/osrsmath/examples/firemaking/summary.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/firemaking/summary.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/firemaking/wintertodt.py:
--------------------------------------------------------------------------------
1 | if __name__ == '__main__':
2 | from osrsmath.skills.firemaking.wintertodt import *
3 | import matplotlib.pyplot as plt
4 | import matplotlib as mpl
5 | import time
6 |
7 | plt.style.use('seaborn-poster')
8 | mpl.rcParams['xtick.labelsize'] = 20
9 | mpl.rcParams['ytick.labelsize'] = 20
10 | fontsize = 30
11 | legendsize = 20
12 |
13 | start = time.time()
14 | e50, e99 = experience(50), experience(99)
15 |
16 | ## Plotting kills vs points for 50-99 fm, for different policies
17 | policies = {
18 | 'Roots': [],
19 | 'Kindling': [],
20 | 'Kindling Till Bonus': [],
21 | }
22 |
23 | # point_list = list(range(25, 2000+25, 1))
24 | # for points in point_list:
25 | # policies['Roots'].append((points, kills_for_xp(e50, e99, points, Policies.roots_only)))
26 | # policies['Kindling'].append((points, kills_for_xp(e50, e99, points, Policies.kindling_only)))
27 | # policies['Kindling Till Bonus'].append((points, kills_for_xp(e50, e99, points, Policies.kindling_till_bonus)))
28 | # print(points)
29 |
30 | # for policy, data in policies.items():
31 | # plt.plot(*list(zip(*data)), label=f"Policy={policy}", linewidth=8)
32 | # plt.ylabel('Kills Required for 50-99 fm', fontsize=fontsize)
33 | # plt.xlabel('Points per Kill', fontsize=fontsize)
34 | # plt.xlim(0, 2000)
35 | # plt.ylim(0, 3000)
36 | # plt.legend(loc='upper right', prop={'size': 1.2*legendsize}, framealpha=0)
37 | # # plt.grid('on')
38 | # print(f'Evaluated in {time.time() - start}.')
39 | # plt.savefig('policies.pdf', transparent=True)
40 | # plt.show()
41 |
42 |
43 | ## Plotting grand exchange value from 50-99 firemaking, for different base levels & points per game,
44 | # for a fixed policy.
45 | # Values obtained from https://oldschool.runescape.wiki/w/Calculator:Wintertodt_supply_crate on 2020-11-04
46 | # for 500 points. So, each value is later divided by two since 500 points the value for 2 rolls.
47 | roll_values = {
48 | ( 1, 500): 6_799.85,
49 | ( 1, 750): 8_308.68,
50 | ( 1, 1000): 9_817.50,
51 | # ( 1, 5000): 33_958.73,
52 | (40, 500): 12_371.24,
53 | (40, 750): 15_272.91,
54 | (40, 1000): 18_174.59,
55 | # (40, 5000): 64_601.38,
56 | (75, 500): 16_543.89,
57 | (75, 750): 20_488.73,
58 | (75, 1000): 24_433.57,
59 | # (75, 5000): 87_550.98,
60 | (99, 500): 17_220.78,
61 | (99, 750): 21_334.85,
62 | (99, 1000): 25_448.91,
63 | # (99, 5000): 91_273.88,
64 | }
65 | roll_values = {k: v/2 for k, v in roll_values.items()}
66 | vs_points = {}
67 | vs_base = {}
68 | for (base, points), value in roll_values.items():
69 | kills_required = kills_for_xp(experience(50), experience(99), points, Policies.roots_only)
70 | # kills_required = kills_for_xp(experience(50), experience(99), points, Policies.kindling_only)
71 | total = value*rolls_per_kill(points)*kills_required
72 |
73 | vs_points.setdefault(base, []).append((points, total/1_000_000))
74 | vs_base.setdefault(points, []).append((base, total/1_000_000))
75 |
76 | fig, (ax1, ax2) = plt.subplots(2, 1)
77 | for base in vs_points:
78 | ax1.plot(*list(zip(*vs_points[base])), label=f"Base={base}", linewidth=8)
79 | ax1.scatter(*list(zip(*vs_points[base])), s=300)
80 | ax1.set_ylabel('Profit [Millions]', fontsize=fontsize)
81 | ax1.set_xlabel('Points per kill', fontsize=fontsize)
82 | # ax1.set_xlim(450, 1050)
83 | ax1.set_ylim(top=20)
84 | ax1.legend(loc='upper left', framealpha=0, prop={'size': legendsize}, ncol=4)
85 | # ax1.grid('on')
86 |
87 | for points in vs_base:
88 | ax2.plot(*list(zip(*vs_base[points])), label=f"Points={points}", linewidth=8)
89 | ax2.scatter(*list(zip(*vs_base[points])), s=300)
90 | ax2.set_ylabel('Profit [Millions]', fontsize=fontsize)
91 | ax2.set_xlabel('Base level', fontsize=fontsize)
92 | ax2.set_ylim(top=20)
93 | ax2.legend(loc='upper left', framealpha=0, prop={'size': legendsize}, ncol=3)
94 | # ax2.grid('on')
95 |
96 | fig.tight_layout()
97 | plt.savefig('profit.pdf', transparent=True)
98 | # plt.show()
99 |
--------------------------------------------------------------------------------
/osrsmath/examples/mining/Prospector_boots_detail.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/mining/Prospector_boots_detail.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/mining/Prospector_helmet_detail.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/mining/Prospector_helmet_detail.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/mining/Prospector_jacket_detail.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/mining/Prospector_jacket_detail.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/mining/Prospector_legs_detail.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/mining/Prospector_legs_detail.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/mining/optimal_order.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/mining/optimal_order.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/mining/optimal_prospector_order.py:
--------------------------------------------------------------------------------
1 | from osrsmath.skills.mining.motherload_mine import Miner, base_xp, PROSPECTOR
2 | import itertools
3 |
4 | if __name__ == '__main__':
5 | import cairo # pip install pycairo
6 | from pprint import pprint
7 | from PyPDF2 import PdfFileWriter, PdfFileReader # pip install PyPDF2
8 |
9 | def normalize(dic):
10 | m, M = min(dic.values()), max(dic.values())
11 | return {k: round((v - m) / (M - m), 12) for k, v in dic.items()}
12 |
13 | file_name='optimal_order.pdf'
14 | experience = {}
15 | for item1, item2, item3, item4 in itertools.permutations(PROSPECTOR):
16 | miner = Miner()
17 | miner.obtain(item1)
18 | miner.obtain(item2)
19 | miner.obtain(item3)
20 | miner.obtain(item4)
21 | experience[miner.kit()] = miner.experience_gained - base_xp()
22 | best_order = sorted(experience.items(), key=lambda x: x[1])[-1][0]
23 |
24 | pprint(normalize(experience))
25 | print(best_order)
26 |
27 | with cairo.PDFSurface(file_name, 300, 300) as surface:
28 | context = cairo.Context(surface)
29 | context.scale(250, 250)
30 |
31 | xs = [i / 6 for i in range(1, 6+1)]
32 | ys = list(reversed([i / 6 for i in range(1, 6+1)]))
33 | xl, xr = xs[0], xs[-1]
34 | yb, yt = ys[0], ys[-1]
35 |
36 | def draw(order, item):
37 | i = list(PROSPECTOR).index(item) + 1
38 | if order == 1:
39 | context.move_to(xl, ys[i])
40 | elif order == 2:
41 | context.line_to(xs[i], yt)
42 | elif order == 3:
43 | context.line_to(xr, ys[i])
44 | elif order == 4:
45 | context.line_to(xs[i], yb)
46 | else:
47 | assert False
48 |
49 | normalized = normalize(experience)
50 | for item1, item2, item3, item4 in itertools.permutations(PROSPECTOR):
51 | kit = (item1, item2, item3, item4)
52 | context.set_line_width( normalized[kit]*normalized[kit] / 50 )
53 | context.set_source_rgb( normalized[kit], 0, 0 )
54 | draw(1, item1)
55 | draw(2, item2)
56 | draw(3, item3)
57 | draw(4, item4)
58 | context.stroke()
59 |
60 | # Add images of the equipment over top of the lines
61 | helmet_page = PdfFileReader('Prospector_helmet_detail.pdf').getPage(0)
62 | jacket_page = PdfFileReader('Prospector_jacket_detail.pdf').getPage(0)
63 | legs_page = PdfFileReader('Prospector_legs_detail.pdf').getPage(0)
64 | boots_page = PdfFileReader('Prospector_boots_detail.pdf').getPage(0)
65 | page = PdfFileReader(file_name).getPage(0)
66 |
67 | # Left
68 | page.mergeScaledTranslatedPage(helmet_page, 0.07, 5, 85)
69 | page.mergeScaledTranslatedPage(jacket_page, 0.07, 5, 125)
70 | page.mergeScaledTranslatedPage(legs_page, 0.07, 5, 165)
71 | page.mergeScaledTranslatedPage(boots_page, 0.07, 5, 205)
72 |
73 | # Top
74 | page.mergeScaledTranslatedPage(helmet_page, 0.07, 65, 270)
75 | page.mergeScaledTranslatedPage(jacket_page, 0.07, 110, 270)
76 | page.mergeScaledTranslatedPage(legs_page, 0.07, 155, 270)
77 | page.mergeScaledTranslatedPage(boots_page, 0.07, 190, 265)
78 |
79 | # Right
80 | page.mergeScaledTranslatedPage(helmet_page, 0.07, 260, 85)
81 | page.mergeScaledTranslatedPage(jacket_page, 0.07, 260, 125)
82 | page.mergeScaledTranslatedPage(legs_page, 0.07, 260, 165)
83 | page.mergeScaledTranslatedPage(boots_page, 0.07, 260, 205)
84 |
85 | # Bottom
86 | page.mergeScaledTranslatedPage(helmet_page, 0.07, 65, 20)
87 | page.mergeScaledTranslatedPage(jacket_page, 0.07, 110, 20)
88 | page.mergeScaledTranslatedPage(legs_page, 0.07, 150, 20)
89 | page.mergeScaledTranslatedPage(boots_page, 0.07, 190, 20)
90 |
91 | # Write to output
92 | pdf_writer = PdfFileWriter()
93 | pdf_writer.addPage(page)
94 | with open(file_name, 'wb') as out:
95 | pdf_writer.write(out)
96 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/osrsmath/examples/mining/sorted.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/mining/sorted.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/mining/sorted.py:
--------------------------------------------------------------------------------
1 | from osrsmath.skills.mining.motherload_mine import Miner, base_xp, PROSPECTOR
2 | import matplotlib.patches as mpatches
3 | import matplotlib.pyplot as plt
4 | from pprint import pprint
5 | import itertools
6 |
7 | def normalize(dic):
8 | m, M = min(dic.values()), max(dic.values())
9 | return {k: round((v - m) / (M - m), 12) for k, v in dic.items()}
10 |
11 | if __name__ == '__main__':
12 | file_name='sorted.pdf'
13 | experience = {}
14 | for item1, item2, item3, item4 in itertools.permutations(PROSPECTOR):
15 | miner = Miner()
16 | miner.obtain(item1)
17 | miner.obtain(item2)
18 | miner.obtain(item3)
19 | miner.obtain(item4)
20 | experience[miner.kit()] = miner.experience_gained - base_xp()
21 | m, M = min(experience.items(), key=lambda x: x[1])[1], max(experience.items(), key=lambda x: x[1])[1]
22 | sort = {''.join(l[0] for l in k): v for k, v in sorted(experience.items(), key=lambda x: x[1])}
23 | x = list(range(len(sort)))
24 |
25 | fig, ax = plt.subplots()
26 | fig.set_size_inches(16, 8)
27 | plt.ylim((m - 100, M + 100))
28 | plt.bar(x, sort.values())
29 | plt.xticks(x, sort.keys())
30 | plt.ylabel('Bonus Experience')
31 | plt.xlabel('Order Obtained')
32 | plt.legend(handles=[
33 | mpatches.Patch(label='J: Jacket'),
34 | mpatches.Patch(label='L: Legs'),
35 | mpatches.Patch(label='H: Helmet'),
36 | mpatches.Patch(label='B: Boots'),
37 | ])
38 | # plt.show()
39 | plt.savefig(file_name)
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/osrsmath/examples/mining/varying_paydirt.100.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/mining/varying_paydirt.100.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/mining/varying_paydirt.100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/mining/varying_paydirt.100.png
--------------------------------------------------------------------------------
/osrsmath/examples/mining/varying_paydirt.1000.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/mining/varying_paydirt.1000.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/mining/varying_paydirt.1000.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/mining/varying_paydirt.1000.png
--------------------------------------------------------------------------------
/osrsmath/examples/mining/varying_paydirt.10000.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/mining/varying_paydirt.10000.pdf
--------------------------------------------------------------------------------
/osrsmath/examples/mining/varying_paydirt.10000.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Palfore/OSRSmath/993fbf73a10dd2e4ad15a27811456c378ece924b/osrsmath/examples/mining/varying_paydirt.10000.png
--------------------------------------------------------------------------------
/osrsmath/examples/mining/varying_paydirt.py:
--------------------------------------------------------------------------------
1 | from osrsmath.skills.mining.motherload_mine import Miner, base_xp, PROSPECTOR
2 | import matplotlib.patches as mpatches
3 | import matplotlib.pyplot as plt
4 | from pprint import pprint
5 | import itertools
6 |
7 | def get_optimal_kit(paydirt_xp):
8 | experience = {}
9 | for item1, item2, item3, item4 in itertools.permutations(PROSPECTOR):
10 | miner = Miner(xp_per_paydirt=paydirt_xp)
11 | miner.obtain(item1)
12 | miner.obtain(item2)
13 | miner.obtain(item3)
14 | miner.obtain(item4)
15 | experience[miner.kit()] = miner.experience_gained - base_xp(paydirt_xp)
16 | return {''.join(l[0] for l in k): v for k, v in sorted(experience.items(), key=lambda x: x[1])}
17 |
18 | if __name__ == '__main__':
19 | file_prefix='varying_paydirt'
20 | data = {}
21 | for paydirt_xp in range(2, 10_000):
22 | x = list(reversed(list(enumerate(reversed(get_optimal_kit(paydirt_xp).keys()), 1))))
23 | data[paydirt_xp] = {y: i for i, y in x}
24 |
25 | plot = {}
26 | for key in data[60]:
27 | plot[key] = ((
28 | list(data.keys()), [
29 | datum[key] for paydirt_xp, datum in data.items()
30 | ]))
31 |
32 | for x_max in [100, 1_000, 10_000]:
33 | fig, ax = plt.subplots()
34 | fig.set_size_inches(16, 8)
35 | for i, (key, (x, y)) in enumerate(plot.items()):
36 | plt.plot(x[:x_max], y[:x_max], label=key)
37 | plt.plot([60, 60], [0, 25], color='black')
38 | plt.ylabel('Ranking', fontsize=18)
39 | plt.xlabel('Paydirt Experience', fontsize=18)
40 | ax.tick_params(axis='both', which='major', labelsize=16)
41 | ax.tick_params(axis='both', which='minor', labelsize=10)
42 | plt.legend(loc='right')
43 | plt.savefig(f'{file_prefix}.{x_max}.pdf')
44 | plt.savefig(f'{file_prefix}.{x_max}.png')
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/osrsmath/examples/quests/model/README.md:
--------------------------------------------------------------------------------
1 | # Runescape Quest Visualizer
2 |
3 | This package implements an interactive quest graph.
4 |
5 | ## Overview
6 |
7 | - Quest.py: Models Skill, Skills, Quest, QuestBook, and Player
8 | - Wiki_quest_parser.py: Implements WikiQuestParser for wiki web scraping.
9 | - There are two versions of this, one for OSRS and one for RS3.
10 | - Quest_view: Implements the graph generation.
11 |
12 | ## Usage
13 |
14 | - To use this implementation run `python quest_view.py`, which will generate the output files. Add the flag `--rs3` to compile the runescape3 graph instead of the osrs graph.
15 | - The output files are "by_quest.pdf", "by_requirement.pdf", and "quest_viewer.html".
16 | - Note: To host quest_viewer.html, you could replace the javascript contents of the `