From 03ca2cbfad12b768cdd6a1d2d6f2626ef4f15ff5 Mon Sep 17 00:00:00 2001
From: Umar Sharief
<80610051+noneofyourbusiness1415252@users.noreply.github.com>
Date: Fri, 24 Jan 2025 22:55:27 +0000
Subject: [PATCH 01/78] initial: maze game
---
Cargo.toml | 17 +-
LICENSE_APACHE | 201 -------------------
LICENSE_MIT | 25 ---
cognitive-games | 1 +
index.html | 66 +++++++
src/lib.rs | 498 +++++++++++++++++++++++++++++++++++++++++++++++-
6 files changed, 571 insertions(+), 237 deletions(-)
delete mode 100644 LICENSE_APACHE
delete mode 100644 LICENSE_MIT
create mode 160000 cognitive-games
create mode 100644 index.html
diff --git a/Cargo.toml b/Cargo.toml
index 2383054..4ff2cc9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
[package]
-name = "{{project-name}}"
+name = "cognitive-games"
version = "0.1.0"
-authors = ["{{authors}}"]
+authors = ["Umar Sharief"]
edition = "2018"
[lib]
@@ -18,6 +18,19 @@ wasm-bindgen = "0.2.84"
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.7", optional = true }
+js-sys = "0.3.77"
+web-sys = { version = "0.3", features = [
+ "Document",
+ "Element",
+ "HtmlElement",
+ "Window",
+ "MouseEvent",
+ "DomTokenList",
+ "console",
+ "HtmlDialogElement",
+ "CustomEvent",
+ "CustomEventInit",
+]}
[dev-dependencies]
wasm-bindgen-test = "0.3.34"
diff --git a/LICENSE_APACHE b/LICENSE_APACHE
deleted file mode 100644
index 11069ed..0000000
--- a/LICENSE_APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/LICENSE_MIT b/LICENSE_MIT
deleted file mode 100644
index a15266c..0000000
--- a/LICENSE_MIT
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2018 {{authors}}
-
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/cognitive-games b/cognitive-games
new file mode 160000
index 0000000..e395998
--- /dev/null
+++ b/cognitive-games
@@ -0,0 +1 @@
+Subproject commit e395998a79e6206821aeb10196e39cc48b7b77c4
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..5cab30b
--- /dev/null
+++ b/index.html
@@ -0,0 +1,66 @@
+
+
+
+
+ WASM Maze Game
+
+
+
+
+ Level: 1 |
+ Completed: 0 |
+ Time: 5:00
+
+
+
+
+
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index 3437786..ff16a84 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,13 +1,493 @@
-mod utils;
-
use wasm_bindgen::prelude::*;
-
-#[wasm_bindgen]
-extern "C" {
- fn alert(s: &str);
+use web_sys::{console, Document, Element, HtmlElement};
+use js_sys::Math;
+use std::{cell::RefCell, collections::HashSet, rc::Rc};
+#[wasm_bindgen(start)]
+pub fn start() {
+ console_error_panic_hook::set_once();
}
-
#[wasm_bindgen]
-pub fn greet() {
- alert("Hello, {{project-name}}!");
+#[derive(Clone)]
+pub struct MazeGame {
+ // Game state
+ size: usize,
+ level: usize,
+ mazes_completed: usize,
+
+ // Maze elements
+ walls: Vec,
+ current_position: (usize, usize),
+ key_position: (usize, usize),
+ door_position: (usize, usize),
+ visited: HashSet<(usize, usize)>,
+ has_key: bool,
+
+ // Timer state
+ time_remaining: i32,
+ last_tick: f64,
+
+ // DOM reference
+ document: Document,
}
+#[wasm_bindgen]
+impl MazeGame {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Result {
+ console::log_1(&"Creating new game".into());
+ let window = web_sys::window().expect("no global window exists");
+ let document = window.document().expect("no document exists");
+ let size = 2;
+ let mut game = MazeGame::create_maze(size, document);
+ game.render()?;
+ game.start()?;
+ Ok(game)
+ }
+
+ fn create_maze(size: usize, document: Document) -> MazeGame {
+ let mut walls = vec![false; size * size * 4]; // Start with no walls
+
+ // Add random walls
+ for i in 0..walls.len() {
+ walls[i] = Math::random() < 0.5;
+ }
+
+ // Generate door positions
+ let door_x = (Math::random() * (size as f64)).floor() as usize;
+ let door_y = (Math::random() * (size as f64)).floor() as usize;
+
+ let mut attempts = 0;
+ // Generate key position that's accessible without going through door
+ let key_position = loop {
+ let key_x = (Math::random() * (size as f64)).floor() as usize;
+ let key_y = (Math::random() * (size as f64)).floor() as usize;
+ let pos = (key_x, key_y);
+
+ // Ensure key is not at start
+ if pos == (0, 0) {
+ continue;
+ }
+
+ // Create a temporary set of walls for path checking
+ let test_walls = walls.clone();
+ let mut visited = HashSet::new();
+ visited.insert((0, 0));
+
+ // Flood fill from start position
+ let mut stack = vec![(0, 0)];
+ while let Some(current) = stack.pop() {
+ for (dx, dy) in &[(0, 1), (0, -1), (1, 0), (-1, 0)] {
+ let next_x = current.0 as i32 + dx;
+ let next_y = current.1 as i32 + dy;
+
+ if next_x >= 0 && next_x < size as i32 &&
+ next_y >= 0 && next_y < size as i32 {
+ let next = (next_x as usize, next_y as usize);
+
+ // Skip if it's the door position
+ if next == (door_x, door_y) {
+ continue;
+ }
+
+ // Check if path is not blocked by wall
+ let wall_idx = (current.1 * size + current.0) * 4 +
+ if *dx > 0 { 1 } else if *dx < 0 { 3 }
+ else if *dy > 0 { 2 } else { 0 };
+
+ if !test_walls[wall_idx] && !visited.contains(&next) {
+ visited.insert(next);
+ stack.push(next);
+ }
+ }
+ }
+ }
+
+ // If we can reach the key position without going through door
+ if visited.contains(&pos) {
+ break pos;
+ }
+
+ attempts += 1;
+ if attempts > 10 {
+ // Fallback to a safe position if random generation fails
+ break (1, 0);
+ }
+ };
+
+
+ // Generate door position after key is placed
+ let door_position = loop {
+ let door_x = (Math::random() * (size as f64)).floor() as usize;
+ let door_y = (Math::random() * (size as f64)).floor() as usize;
+ let pos = (door_x, door_y);
+
+ // Ensure door is not at start and not at key position
+ if pos != (0, 0) && pos != key_position {
+ break pos;
+ }
+ };
+
+ let mut game = MazeGame {
+ size,
+ walls,
+ current_position: (0, 0),
+ key_position,
+ door_position,
+ visited: HashSet::new(),
+ has_key: false,
+ level: 1,
+ mazes_completed: 0,
+ document,
+ time_remaining: 300,
+ last_tick: js_sys::Date::now() / 1000.0,
+ };
+
+ // Clear path function - ensures a 2-cell wide path
+ fn clear_path(walls: &mut Vec, from: (usize, usize), to: (usize, usize), size: usize) {
+ let mut current = from;
+ while current != to {
+ let dx = (to.0 as i32 - current.0 as i32).signum();
+ let dy = (to.1 as i32 - current.1 as i32).signum();
+
+ // Clear both current cell's wall and neighbor's wall
+ if dx != 0 {
+ let wall_idx = (current.1 * size + current.0) * 4 + if dx > 0 { 1 } else { 3 };
+ walls[wall_idx] = false;
+ // Clear adjacent cell's opposite wall if not at edge
+ if (dx > 0 && current.0 + 1 < size) || (dx < 0 && current.0 > 0) {
+ let next_x = (current.0 as i32 + dx) as usize;
+ let adj_wall_idx = (current.1 * size + next_x) * 4 + if dx > 0 { 3 } else { 1 };
+ walls[adj_wall_idx] = false;
+
+ // Always clear an escape route (up or down)
+ let escape_dir = if current.1 > 0 { 0 } else { 2 }; // up if not at top, down otherwise
+ walls[(current.1 * size + current.0) * 4 + escape_dir] = false;
+ if escape_dir == 0 && current.1 > 0 {
+ // Clear the corresponding wall in the cell above
+ walls[((current.1 - 1) * size + current.0) * 4 + 2] = false;
+ } else if escape_dir == 2 && current.1 + 1 < size {
+ // Clear the corresponding wall in the cell below
+ walls[((current.1 + 1) * size + current.0) * 4 + 0] = false;
+ }
+ }
+ current.0 = (current.0 as i32 + dx) as usize;
+ } else if dy != 0 {
+ let wall_idx = (current.1 * size + current.0) * 4 + if dy > 0 { 2 } else { 0 };
+ walls[wall_idx] = false;
+ // Clear adjacent cell's opposite wall if not at edge
+ if (dy > 0 && current.1 + 1 < size) || (dy < 0 && current.1 > 0) {
+ let next_y = (current.1 as i32 + dy) as usize;
+ let adj_wall_idx = (next_y * size + current.0) * 4 + if dy > 0 { 0 } else { 2 };
+ walls[adj_wall_idx] = false;
+ }
+ current.1 = (current.1 as i32 + dy) as usize;
+ }
+ // Ensure escape route from the destination
+ let escape_dirs = [(0, -1), (0, 1), (-1, 0), (1, 0)]; // up, down, left, right
+ for (dx, dy) in escape_dirs.iter() {
+ let next_x = to.0 as i32 + dx;
+ let next_y = to.1 as i32 + dy;
+ if next_x >= 0 && next_x < size as i32 && next_y >= 0 && next_y < size as i32 {
+ let wall_idx = (to.1 * size + to.0) * 4 +
+ if *dy < 0 { 0 } else if *dx > 0 { 1 } else if *dy > 0 { 2 } else { 3 };
+ walls[wall_idx] = false;
+ }
+ }
+ }
+ }
+
+ // Clear paths with extra space around them
+ clear_path(&mut game.walls, (0, 0), key_position, size);
+ clear_path(&mut game.walls, key_position, door_position, size);
+
+ game.visited.insert((0, 0));
+ game
+ }
+ pub fn render(&self) -> Result<(), JsValue> {
+ let maze = self.document.get_element_by_id("maze").unwrap();
+ maze.set_attribute("style", &format!("grid-template-columns: repeat({}, 60px)", self.size))?;
+ maze.set_inner_html("");
+
+ for y in 0..self.size {
+ for x in 0..self.size {
+ let cell = self.create_cell(x, y)?;
+ maze.append_child(&cell)?;
+ }
+ }
+
+ // Update stats
+ if let Some(level_el) = self.document.get_element_by_id("level") {
+ level_el.set_inner_html(&self.level.to_string());
+ }
+ if let Some(completed_el) = self.document.get_element_by_id("completed") {
+ completed_el.set_inner_html(&self.mazes_completed.to_string());
+ }
+ if let Some(timer_el) = self.document.get_element_by_id("timer") {
+ let minutes = self.time_remaining / 60;
+ let seconds = self.time_remaining % 60;
+ timer_el.set_inner_html(&format!("{}:{:02} !", minutes, seconds)); // Removed v3 suffix
+ }
+ Ok(())
+ }
+ #[wasm_bindgen]
+ pub fn start(&mut self) -> Result<(), JsValue> {
+ let game_state = Rc::new(RefCell::new(self.clone()));
+
+ // Add cell click handler
+ let click_handler = {
+ let game_state = game_state.clone();
+ Closure::wrap(Box::new(move |event: web_sys::CustomEvent| {
+ if let Ok(mut game) = game_state.try_borrow_mut() {
+ let coords = event.detail().as_string().unwrap();
+ let mut coords = coords.split(',');
+ let x = coords.next().unwrap().parse::().unwrap();
+ let y = coords.next().unwrap().parse::().unwrap();
+
+ let result = game.try_move(x, y);
+ game.render().unwrap();
+
+ if let Some(window) = web_sys::window() {
+ match result {
+ -1 => window.alert_with_message("Hit a wall! Starting over.").unwrap(),
+ 2 => window.alert_with_message("Level complete!").unwrap(),
+ _ => {}
+ }
+ }
+ }
+ }) as Box)
+ };
+ if let Some(maze_el) = self.document.get_element_by_id("maze") {
+ maze_el.add_event_listener_with_callback(
+ "cell-click",
+ click_handler.as_ref().unchecked_ref()
+ )?;
+ click_handler.forget();
+ }
+ let f = {
+ let game_state = game_state.clone();
+ Closure::wrap(Box::new(move || {
+ if let Ok(mut game) = game_state.try_borrow_mut() {
+ let now = js_sys::Date::now() / 1000.0;
+ let delta = (now - game.last_tick) as i32;
+ if delta >= 1 {
+ game.time_remaining -= 1;
+ game.last_tick = now;
+
+ if game.time_remaining <= 0 {
+ // Reset maze and timer
+ let new_game = MazeGame::create_maze(game.size, game.document.clone());
+ game.walls = new_game.walls;
+ game.key_position = new_game.key_position;
+ game.door_position = new_game.door_position;
+ game.reset_position();
+ game.time_remaining = 300;
+ game.last_tick = now;
+
+ game.render().unwrap();
+ web_sys::window()
+ .unwrap()
+ .alert_with_message("Time's up! Moving to next maze...")
+ .unwrap();
+ }
+
+ // Update timer display
+ if let Some(timer_el) = game.document.get_element_by_id("timer") {
+ let minutes = game.time_remaining / 60;
+ let seconds = game.time_remaining % 60;
+ timer_el.set_inner_html(&format!("{}:{:02}", minutes, seconds));
+ }
+ }
+ }
+ }) as Box)
+ };
+
+ // Set up interval timer
+ let window = web_sys::window().unwrap();
+ console::log_1(&"Setting up interval...".into());
+ let result = window.set_interval_with_callback_and_timeout_and_arguments_0(
+ f.as_ref().unchecked_ref(),
+ 1000,
+ );
+
+ match result {
+ Ok(_) => console::log_1(&"Interval set up successfully".into()),
+ Err(e) => console::log_2(&"Failed to set up interval:".into(), &e),
+ }
+
+ f.forget();
+ console::log_1(&"Setup complete".into());
+ Ok(())
+ }
+ fn create_cell(&self, x: usize, y: usize) -> Result {
+ let cell = self.document.create_element("div")?;
+ cell.set_class_name("cell");
+
+ // Add visited and current classes
+ if self.visited.contains(&(x, y)) {
+ cell.class_list().add_1("visited")?;
+ }
+ if (x, y) == self.current_position {
+ cell.class_list().add_1("current")?;
+ }
+
+ // Add key and door symbols - only one instance of the key should exist
+ if (x, y) == self.key_position && !self.has_key {
+ cell.set_inner_html("π");
+ } else if (x, y) == self.current_position && self.has_key {
+ cell.set_inner_html("π");
+ } else if (x, y) == self.door_position {
+ cell.set_inner_html("πͺ");
+ }
+
+ // Add chevrons for adjacent cells
+ if self.is_adjacent(x, y) {
+ let chevron = self.document.create_element("span")?;
+ chevron.set_class_name("chevron");
+ let direction = match (x as i32 - self.current_position.0 as i32,
+ y as i32 - self.current_position.1 as i32) {
+ (1, 0) => "right",
+ (-1, 0) => "left",
+ (0, 1) => "down",
+ (0, -1) => "up",
+ _ => unreachable!()
+ };
+ chevron.class_list().add_1(direction)?;
+ chevron.set_text_content(Some("βΊ"));
+ cell.append_child(&chevron)?;
+ }
+
+ let x = x.clone();
+ let y = y.clone();
+ let click_callback = Closure::wrap(Box::new(move |_event: web_sys::MouseEvent| {
+ if let Some(window) = web_sys::window() {
+ if let Some(doc) = window.document() {
+ if let Some(maze_el) = doc.get_element_by_id("maze") {
+ let event_init = web_sys::CustomEventInit::new();
+ event_init.set_detail(&JsValue::from_str(&format!("{},{}", x, y)));
+ let event = web_sys::CustomEvent::new_with_event_init_dict(
+ "cell-click",
+ &event_init
+ ).unwrap();
+ maze_el.dispatch_event(&event).unwrap();
+ }
+ }
+ }
+ }) as Box);
+ let cell_element: &HtmlElement = cell.dyn_ref().unwrap();
+ cell_element.set_onclick(Some(click_callback.as_ref().unchecked_ref()));
+ click_callback.forget();
+ Ok(cell)
+ }
+ fn is_adjacent(&self, x: usize, y: usize) -> bool {
+ let current_x = self.current_position.0;
+ let current_y = self.current_position.1;
+
+ // Check if target position is adjacent (up, down, left, right)
+ let dx = if x >= current_x { x - current_x } else { current_x - x };
+ let dy = if y >= current_y { y - current_y } else { current_y - y };
+
+ // Only one coordinate can change by 1, the other must be 0
+ (dx == 1 && dy == 0) || (dx == 0 && dy == 1)
+ }
+
+ fn get_wall_index(&self, from_x: usize, from_y: usize, to_x: usize, to_y: usize) -> usize {
+ let cell_walls = 4; // each cell has 4 possible walls
+ let base_index = (from_y * self.size + from_x) * cell_walls;
+
+ if to_x > from_x {
+ base_index + 1 // right wall
+ } else if to_x < from_x {
+ base_index + 3 // left wall
+ } else if to_y > from_y {
+ base_index + 2 // bottom wall
+ } else {
+ base_index + 0 // top wall
+ }
+ }
+
+ fn level_up(&mut self) {
+ self.size += 1;
+ self.level += 1;
+ self.mazes_completed = 0;
+
+ // Create new maze with increased size
+ let new_game = MazeGame::create_maze(self.size, self.document.clone());
+ self.walls = new_game.walls;
+ self.current_position = (0, 0);
+ self.key_position = new_game.key_position;
+ self.door_position = new_game.door_position;
+ self.visited.clear();
+ self.visited.insert((0, 0));
+ self.has_key = false;
+ self.render().expect("Failed to render new level");
+ }
+
+ #[wasm_bindgen]
+ pub fn try_move(&mut self, x: usize, y: usize) -> i32 {
+ if !self.is_adjacent(x, y) {
+ return 0; // Invalid move
+ }
+
+ // Check for wall
+ let wall_idx = self.get_wall_index(
+ self.current_position.0,
+ self.current_position.1,
+ x,
+ y
+ );
+ if self.walls[wall_idx] {
+ self.reset_position();
+ return -1; // Hit wall
+ }
+
+ // Update position
+ self.current_position = (x, y);
+ self.visited.insert((x, y));
+
+ // Check for key
+ if (x, y) == self.key_position {
+ self.has_key = true;
+ }
+
+ // Check win condition
+ if (x, y) == self.door_position && self.has_key {
+ self.mazes_completed += 1;
+
+ if self.mazes_completed >= (self.size - 1).pow(2) {
+ self.level_up();
+ } else {
+ // New maze - reset timer and maze
+ self.reset();
+ }
+ return 2; // Won
+ }
+ 1 // Valid move
+ }
+ #[wasm_bindgen]
+ pub fn reset(&mut self) {
+ let new_game = MazeGame::create_maze(self.size, self.document.clone());
+ self.walls = new_game.walls;
+ self.key_position = new_game.key_position;
+ self.door_position = new_game.door_position;
+ self.reset_position();
+
+ // Reset timer state completely
+ self.time_remaining = 300;
+ self.last_tick = js_sys::Date::now() / 1000.0;
+
+ // Force timer display update
+ if let Some(timer_el) = self.document.get_element_by_id("timer") {
+ timer_el.set_inner_html("5:00");
+ }
+
+ // Update display
+ self.render().expect("Failed to render reset");
+ }
+ fn reset_position(&mut self) {
+ self.current_position = (0, 0);
+ self.visited.clear();
+ self.visited.insert((0, 0));
+ self.has_key = false;
+ self.render().expect("Failed to render position reset");
+ }
+ // Additional helper methods...
+}
\ No newline at end of file
From ef95ee1ffff304da853902cd7a39c3e8c46ce493 Mon Sep 17 00:00:00 2001
From: Umar Sharief
<80610051+noneofyourbusiness1415252@users.noreply.github.com>
Date: Fri, 24 Jan 2025 23:03:05 +0000
Subject: [PATCH 02/78] remove unnecessary
---
cognitive-games | 1 -
1 file changed, 1 deletion(-)
delete mode 160000 cognitive-games
diff --git a/cognitive-games b/cognitive-games
deleted file mode 160000
index e395998..0000000
--- a/cognitive-games
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit e395998a79e6206821aeb10196e39cc48b7b77c4
From 48b30be7bb1246fef3c6ba9b358ac7deccefeba9 Mon Sep 17 00:00:00 2001
From: Umar Sharief
<80610051+noneofyourbusiness1415252@users.noreply.github.com>
Date: Sat, 25 Jan 2025 12:06:01 +0000
Subject: [PATCH 03/78] prepare for cloudflare pages
---
src/lib.rs | 289 ++++++++++++++++++++++++++++----------------------
wrangler.toml | 11 ++
2 files changed, 171 insertions(+), 129 deletions(-)
create mode 100644 wrangler.toml
diff --git a/src/lib.rs b/src/lib.rs
index ff16a84..7eccc29 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,7 @@
-use wasm_bindgen::prelude::*;
-use web_sys::{console, Document, Element, HtmlElement};
use js_sys::Math;
use std::{cell::RefCell, collections::HashSet, rc::Rc};
+use wasm_bindgen::prelude::*;
+use web_sys::{console, Document, Element, HtmlElement};
#[wasm_bindgen(start)]
pub fn start() {
console_error_panic_hook::set_once();
@@ -13,7 +13,7 @@ pub struct MazeGame {
size: usize,
level: usize,
mazes_completed: usize,
-
+
// Maze elements
walls: Vec,
current_position: (usize, usize),
@@ -21,16 +21,16 @@ pub struct MazeGame {
door_position: (usize, usize),
visited: HashSet<(usize, usize)>,
has_key: bool,
-
+
// Timer state
time_remaining: i32,
last_tick: f64,
-
+
// DOM reference
document: Document,
}
#[wasm_bindgen]
-impl MazeGame {
+impl MazeGame {
#[wasm_bindgen(constructor)]
pub fn new() -> Result {
console::log_1(&"Creating new game".into());
@@ -44,88 +44,93 @@ impl MazeGame {
}
fn create_maze(size: usize, document: Document) -> MazeGame {
- let mut walls = vec![false; size * size * 4]; // Start with no walls
-
+ let mut walls = vec![false; size * size * 4]; // Start with no walls
+
// Add random walls
for i in 0..walls.len() {
walls[i] = Math::random() < 0.5;
}
-
+
// Generate door positions
let door_x = (Math::random() * (size as f64)).floor() as usize;
let door_y = (Math::random() * (size as f64)).floor() as usize;
-
+
let mut attempts = 0;
- // Generate key position that's accessible without going through door
- let key_position = loop {
- let key_x = (Math::random() * (size as f64)).floor() as usize;
- let key_y = (Math::random() * (size as f64)).floor() as usize;
- let pos = (key_x, key_y);
-
- // Ensure key is not at start
- if pos == (0, 0) {
- continue;
- }
+ // Generate key position that's accessible without going through door
+ let key_position = loop {
+ let key_x = (Math::random() * (size as f64)).floor() as usize;
+ let key_y = (Math::random() * (size as f64)).floor() as usize;
+ let pos = (key_x, key_y);
- // Create a temporary set of walls for path checking
- let test_walls = walls.clone();
- let mut visited = HashSet::new();
- visited.insert((0, 0));
-
- // Flood fill from start position
- let mut stack = vec![(0, 0)];
- while let Some(current) = stack.pop() {
- for (dx, dy) in &[(0, 1), (0, -1), (1, 0), (-1, 0)] {
- let next_x = current.0 as i32 + dx;
- let next_y = current.1 as i32 + dy;
-
- if next_x >= 0 && next_x < size as i32 &&
- next_y >= 0 && next_y < size as i32 {
- let next = (next_x as usize, next_y as usize);
-
- // Skip if it's the door position
- if next == (door_x, door_y) {
- continue;
- }
-
- // Check if path is not blocked by wall
- let wall_idx = (current.1 * size + current.0) * 4 +
- if *dx > 0 { 1 } else if *dx < 0 { 3 }
- else if *dy > 0 { 2 } else { 0 };
-
- if !test_walls[wall_idx] && !visited.contains(&next) {
- visited.insert(next);
- stack.push(next);
+ // Ensure key is not at start
+ if pos == (0, 0) {
+ continue;
+ }
+
+ // Create a temporary set of walls for path checking
+ let test_walls = walls.clone();
+ let mut visited = HashSet::new();
+ visited.insert((0, 0));
+
+ // Flood fill from start position
+ let mut stack = vec![(0, 0)];
+ while let Some(current) = stack.pop() {
+ for (dx, dy) in &[(0, 1), (0, -1), (1, 0), (-1, 0)] {
+ let next_x = current.0 as i32 + dx;
+ let next_y = current.1 as i32 + dy;
+
+ if next_x >= 0 && next_x < size as i32 && next_y >= 0 && next_y < size as i32 {
+ let next = (next_x as usize, next_y as usize);
+
+ // Skip if it's the door position
+ if next == (door_x, door_y) {
+ continue;
+ }
+
+ // Check if path is not blocked by wall
+ let wall_idx = (current.1 * size + current.0) * 4
+ + if *dx > 0 {
+ 1
+ } else if *dx < 0 {
+ 3
+ } else if *dy > 0 {
+ 2
+ } else {
+ 0
+ };
+
+ if !test_walls[wall_idx] && !visited.contains(&next) {
+ visited.insert(next);
+ stack.push(next);
+ }
}
}
}
- }
-
- // If we can reach the key position without going through door
- if visited.contains(&pos) {
- break pos;
- }
-
- attempts += 1;
- if attempts > 10 {
- // Fallback to a safe position if random generation fails
- break (1, 0);
- }
- };
-
+ // If we can reach the key position without going through door
+ if visited.contains(&pos) {
+ break pos;
+ }
+
+ attempts += 1;
+ if attempts > 10 {
+ // Fallback to a safe position if random generation fails
+ break (1, 0);
+ }
+ };
+
// Generate door position after key is placed
let door_position = loop {
let door_x = (Math::random() * (size as f64)).floor() as usize;
let door_y = (Math::random() * (size as f64)).floor() as usize;
let pos = (door_x, door_y);
-
+
// Ensure door is not at start and not at key position
if pos != (0, 0) && pos != key_position {
break pos;
}
};
-
+
let mut game = MazeGame {
size,
walls,
@@ -140,14 +145,19 @@ impl MazeGame {
time_remaining: 300,
last_tick: js_sys::Date::now() / 1000.0,
};
-
+
// Clear path function - ensures a 2-cell wide path
- fn clear_path(walls: &mut Vec, from: (usize, usize), to: (usize, usize), size: usize) {
+ fn clear_path(
+ walls: &mut Vec,
+ from: (usize, usize),
+ to: (usize, usize),
+ size: usize,
+ ) {
let mut current = from;
while current != to {
let dx = (to.0 as i32 - current.0 as i32).signum();
let dy = (to.1 as i32 - current.1 as i32).signum();
-
+
// Clear both current cell's wall and neighbor's wall
if dx != 0 {
let wall_idx = (current.1 * size + current.0) * 4 + if dx > 0 { 1 } else { 3 };
@@ -155,9 +165,10 @@ impl MazeGame {
// Clear adjacent cell's opposite wall if not at edge
if (dx > 0 && current.0 + 1 < size) || (dx < 0 && current.0 > 0) {
let next_x = (current.0 as i32 + dx) as usize;
- let adj_wall_idx = (current.1 * size + next_x) * 4 + if dx > 0 { 3 } else { 1 };
+ let adj_wall_idx =
+ (current.1 * size + next_x) * 4 + if dx > 0 { 3 } else { 1 };
walls[adj_wall_idx] = false;
-
+
// Always clear an escape route (up or down)
let escape_dir = if current.1 > 0 { 0 } else { 2 }; // up if not at top, down otherwise
walls[(current.1 * size + current.0) * 4 + escape_dir] = false;
@@ -176,35 +187,47 @@ impl MazeGame {
// Clear adjacent cell's opposite wall if not at edge
if (dy > 0 && current.1 + 1 < size) || (dy < 0 && current.1 > 0) {
let next_y = (current.1 as i32 + dy) as usize;
- let adj_wall_idx = (next_y * size + current.0) * 4 + if dy > 0 { 0 } else { 2 };
+ let adj_wall_idx =
+ (next_y * size + current.0) * 4 + if dy > 0 { 0 } else { 2 };
walls[adj_wall_idx] = false;
}
current.1 = (current.1 as i32 + dy) as usize;
}
- // Ensure escape route from the destination
- let escape_dirs = [(0, -1), (0, 1), (-1, 0), (1, 0)]; // up, down, left, right
- for (dx, dy) in escape_dirs.iter() {
- let next_x = to.0 as i32 + dx;
- let next_y = to.1 as i32 + dy;
- if next_x >= 0 && next_x < size as i32 && next_y >= 0 && next_y < size as i32 {
- let wall_idx = (to.1 * size + to.0) * 4 +
- if *dy < 0 { 0 } else if *dx > 0 { 1 } else if *dy > 0 { 2 } else { 3 };
- walls[wall_idx] = false;
- }
- }
+ // Ensure escape route from the destination
+ let escape_dirs = [(0, -1), (0, 1), (-1, 0), (1, 0)]; // up, down, left, right
+ for (dx, dy) in escape_dirs.iter() {
+ let next_x = to.0 as i32 + dx;
+ let next_y = to.1 as i32 + dy;
+ if next_x >= 0 && next_x < size as i32 && next_y >= 0 && next_y < size as i32 {
+ let wall_idx = (to.1 * size + to.0) * 4
+ + if *dy < 0 {
+ 0
+ } else if *dx > 0 {
+ 1
+ } else if *dy > 0 {
+ 2
+ } else {
+ 3
+ };
+ walls[wall_idx] = false;
+ }
+ }
}
}
-
+
// Clear paths with extra space around them
clear_path(&mut game.walls, (0, 0), key_position, size);
clear_path(&mut game.walls, key_position, door_position, size);
-
+
game.visited.insert((0, 0));
game
}
- pub fn render(&self) -> Result<(), JsValue> {
+ pub fn render(&self) -> Result<(), JsValue> {
let maze = self.document.get_element_by_id("maze").unwrap();
- maze.set_attribute("style", &format!("grid-template-columns: repeat({}, 60px)", self.size))?;
+ maze.set_attribute(
+ "style",
+ &format!("grid-template-columns: repeat({}, 60px)", self.size),
+ )?;
maze.set_inner_html("");
for y in 0..self.size {
@@ -225,13 +248,13 @@ impl MazeGame {
let minutes = self.time_remaining / 60;
let seconds = self.time_remaining % 60;
timer_el.set_inner_html(&format!("{}:{:02} !", minutes, seconds)); // Removed v3 suffix
- }
+ }
Ok(())
}
#[wasm_bindgen]
pub fn start(&mut self) -> Result<(), JsValue> {
let game_state = Rc::new(RefCell::new(self.clone()));
-
+
// Add cell click handler
let click_handler = {
let game_state = game_state.clone();
@@ -241,13 +264,15 @@ impl MazeGame {
let mut coords = coords.split(',');
let x = coords.next().unwrap().parse::().unwrap();
let y = coords.next().unwrap().parse::().unwrap();
-
+
let result = game.try_move(x, y);
game.render().unwrap();
-
+
if let Some(window) = web_sys::window() {
match result {
- -1 => window.alert_with_message("Hit a wall! Starting over.").unwrap(),
+ -1 => window
+ .alert_with_message("Hit a wall! Starting over.")
+ .unwrap(),
2 => window.alert_with_message("Level complete!").unwrap(),
_ => {}
}
@@ -258,7 +283,7 @@ impl MazeGame {
if let Some(maze_el) = self.document.get_element_by_id("maze") {
maze_el.add_event_listener_with_callback(
"cell-click",
- click_handler.as_ref().unchecked_ref()
+ click_handler.as_ref().unchecked_ref(),
)?;
click_handler.forget();
}
@@ -271,7 +296,7 @@ impl MazeGame {
if delta >= 1 {
game.time_remaining -= 1;
game.last_tick = now;
-
+
if game.time_remaining <= 0 {
// Reset maze and timer
let new_game = MazeGame::create_maze(game.size, game.document.clone());
@@ -281,14 +306,14 @@ impl MazeGame {
game.reset_position();
game.time_remaining = 300;
game.last_tick = now;
-
+
game.render().unwrap();
web_sys::window()
.unwrap()
.alert_with_message("Time's up! Moving to next maze...")
.unwrap();
}
-
+
// Update timer display
if let Some(timer_el) = game.document.get_element_by_id("timer") {
let minutes = game.time_remaining / 60;
@@ -299,7 +324,7 @@ impl MazeGame {
}
}) as Box)
};
-
+
// Set up interval timer
let window = web_sys::window().unwrap();
console::log_1(&"Setting up interval...".into());
@@ -307,12 +332,12 @@ impl MazeGame {
f.as_ref().unchecked_ref(),
1000,
);
-
+
match result {
Ok(_) => console::log_1(&"Interval set up successfully".into()),
Err(e) => console::log_2(&"Failed to set up interval:".into(), &e),
}
-
+
f.forget();
console::log_1(&"Setup complete".into());
Ok(())
@@ -320,7 +345,7 @@ impl MazeGame {
fn create_cell(&self, x: usize, y: usize) -> Result {
let cell = self.document.create_element("div")?;
cell.set_class_name("cell");
-
+
// Add visited and current classes
if self.visited.contains(&(x, y)) {
cell.class_list().add_1("visited")?;
@@ -328,7 +353,7 @@ impl MazeGame {
if (x, y) == self.current_position {
cell.class_list().add_1("current")?;
}
-
+
// Add key and door symbols - only one instance of the key should exist
if (x, y) == self.key_position && !self.has_key {
cell.set_inner_html("π");
@@ -336,19 +361,21 @@ impl MazeGame {
cell.set_inner_html("π");
} else if (x, y) == self.door_position {
cell.set_inner_html("πͺ");
- }
-
+ }
+
// Add chevrons for adjacent cells
if self.is_adjacent(x, y) {
let chevron = self.document.create_element("span")?;
chevron.set_class_name("chevron");
- let direction = match (x as i32 - self.current_position.0 as i32,
- y as i32 - self.current_position.1 as i32) {
+ let direction = match (
+ x as i32 - self.current_position.0 as i32,
+ y as i32 - self.current_position.1 as i32,
+ ) {
(1, 0) => "right",
(-1, 0) => "left",
(0, 1) => "down",
(0, -1) => "up",
- _ => unreachable!()
+ _ => unreachable!(),
};
chevron.class_list().add_1(direction)?;
chevron.set_text_content(Some("βΊ"));
@@ -356,7 +383,7 @@ impl MazeGame {
}
let x = x.clone();
- let y = y.clone();
+ let y = y.clone();
let click_callback = Closure::wrap(Box::new(move |_event: web_sys::MouseEvent| {
if let Some(window) = web_sys::window() {
if let Some(doc) = window.document() {
@@ -365,8 +392,9 @@ impl MazeGame {
event_init.set_detail(&JsValue::from_str(&format!("{},{}", x, y)));
let event = web_sys::CustomEvent::new_with_event_init_dict(
"cell-click",
- &event_init
- ).unwrap();
+ &event_init,
+ )
+ .unwrap();
maze_el.dispatch_event(&event).unwrap();
}
}
@@ -380,11 +408,19 @@ impl MazeGame {
fn is_adjacent(&self, x: usize, y: usize) -> bool {
let current_x = self.current_position.0;
let current_y = self.current_position.1;
-
+
// Check if target position is adjacent (up, down, left, right)
- let dx = if x >= current_x { x - current_x } else { current_x - x };
- let dy = if y >= current_y { y - current_y } else { current_y - y };
-
+ let dx = if x >= current_x {
+ x - current_x
+ } else {
+ current_x - x
+ };
+ let dy = if y >= current_y {
+ y - current_y
+ } else {
+ current_y - y
+ };
+
// Only one coordinate can change by 1, the other must be 0
(dx == 1 && dy == 0) || (dx == 0 && dy == 1)
}
@@ -392,7 +428,7 @@ impl MazeGame {
fn get_wall_index(&self, from_x: usize, from_y: usize, to_x: usize, to_y: usize) -> usize {
let cell_walls = 4; // each cell has 4 possible walls
let base_index = (from_y * self.size + from_x) * cell_walls;
-
+
if to_x > from_x {
base_index + 1 // right wall
} else if to_x < from_x {
@@ -408,7 +444,7 @@ impl MazeGame {
self.size += 1;
self.level += 1;
self.mazes_completed = 0;
-
+
// Create new maze with increased size
let new_game = MazeGame::create_maze(self.size, self.document.clone());
self.walls = new_game.walls;
@@ -426,32 +462,27 @@ impl MazeGame {
if !self.is_adjacent(x, y) {
return 0; // Invalid move
}
-
+
// Check for wall
- let wall_idx = self.get_wall_index(
- self.current_position.0,
- self.current_position.1,
- x,
- y
- );
+ let wall_idx = self.get_wall_index(self.current_position.0, self.current_position.1, x, y);
if self.walls[wall_idx] {
self.reset_position();
return -1; // Hit wall
}
-
+
// Update position
self.current_position = (x, y);
self.visited.insert((x, y));
-
+
// Check for key
if (x, y) == self.key_position {
self.has_key = true;
}
-
+
// Check win condition
if (x, y) == self.door_position && self.has_key {
self.mazes_completed += 1;
-
+
if self.mazes_completed >= (self.size - 1).pow(2) {
self.level_up();
} else {
@@ -469,16 +500,16 @@ impl MazeGame {
self.key_position = new_game.key_position;
self.door_position = new_game.door_position;
self.reset_position();
-
+
// Reset timer state completely
self.time_remaining = 300;
self.last_tick = js_sys::Date::now() / 1000.0;
-
+
// Force timer display update
if let Some(timer_el) = self.document.get_element_by_id("timer") {
timer_el.set_inner_html("5:00");
}
-
+
// Update display
self.render().expect("Failed to render reset");
}
@@ -490,4 +521,4 @@ impl MazeGame {
self.render().expect("Failed to render position reset");
}
// Additional helper methods...
-}
\ No newline at end of file
+}
diff --git a/wrangler.toml b/wrangler.toml
new file mode 100644
index 0000000..99cbacb
--- /dev/null
+++ b/wrangler.toml
@@ -0,0 +1,11 @@
+name = "wasm-pack-template"
+compatibility_date = "2024-01-25"
+
+[build]
+command = "curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh && wasm-pack build --target web"
+output_directory = "pkg"name = "wasm-pack-template"
+compatibility_date = "2024-01-25"
+
+[build]
+command = "curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh && wasm-pack build --target web"
+output_directory = "pkg"
\ No newline at end of file
From 4da49e45373137c2ddca17c2c36c7d483dd132a0 Mon Sep 17 00:00:00 2001
From: Umar Sharief
<80610051+noneofyourbusiness1415252@users.noreply.github.com>
Date: Sat, 25 Jan 2025 12:38:06 +0000
Subject: [PATCH 04/78] make index.html move to `pkg` on build
---
index.html | 2 +-
wrangler.toml | 11 -----------
2 files changed, 1 insertion(+), 12 deletions(-)
delete mode 100644 wrangler.toml
diff --git a/index.html b/index.html
index 5cab30b..cff4835 100644
--- a/index.html
+++ b/index.html
@@ -52,7 +52,7 @@
-