---
# System prepended metadata

title: MVP basic loop
tags: [infinite seas]

---

# MVP basic loop

mvp玩法很简单:

ddl: 5/17

### changelog 已在下面修改
**5/5 更新**
- 更新了出海航行消耗的energy，从原来的1小时消耗10个token，改成1小时每艘船消耗5个token
- 改变combat前端的显示，原先的combat为交互回合制，需要玩家每回合按按钮决定策略。现在为当玩家在地图上点击”auto-attack“后，直接显示自动战斗的结果（跳转到结算页面），结算页面美术正在更新，草图见下方。每回合执行的默认为”normal attack“，mvp暂时取消swap和pass逻辑。
- points积分变化，从原先按照每个roster计分，改为按照每艘计分；只要打败对方的船，战斗输了也能拿到积分。points计算变化见下方。



## Login
zklogins: https://docs.sui.io/concepts/cryptography/zklogin

→ User click a DApp that supports Zklogin
→ Signs in via Google, Facebook or twitch
→ A unique public address is created with JWT token tied towards salt service( dev parts lol)
→ A txn is signed and user is identified with a unique address.

## Energy Token
→ User gets 100000 Sui test Token after connecting the wallet.

- 获取：
User can start claiming Energy Token after connecting their wallet. First time claiming is 500, and 200 every 24 hours after. Energy Token max capacity is 1000
- 消耗
资源采集，船队建造，出海航行和战斗都消耗相应的energytoken，消耗如下

| Activity | Details | Energy Token Cost | Time |
|---|---|---|---|
| **资源采集 (Resource Gathering)** | | | |
| Mine 1 copper ore | | 1 | 3 seconds |
| Cut 1 normal wood | | 1 | 3 seconds |
| Plant 1 seed | Yield: 5 cottons | 5 | 15 seconds |
| **船队建造 (Ship Building)** | | | |
| Craft 1 ship | Requires: 15 resources (at least 3 coppers, 3 woods, 3 cottons) | 5 | 15 seconds |
| **出海航行 (Sailing)** | | | |
| ~~1 hour sailing~~ 1 hr sailing per ship | | ~~10~~ 5| 1 hour |




## 地图

### 1. 显示岛屿，船

<img src="https://hackmd.io/_uploads/B1YZwWZx0.jpg" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">

<img src="https://hackmd.io/_uploads/BkdZchieC.png" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">


**Action Queue**
* 当玩家执行action时 (mining&woodcutting&planting&crafting&sailing) 时, 所剩余时常会在左边的queue中排列


#### 岛屿
**点击岛屿** 显示:
在玩家有岛屿的状态下, 左击鼠标点击island时, 会显示以下4个信息: 
→ **owner:** 0xf3... 钱包地址; 如果钱包地址 == 玩家自己钱包的地址, 则显示 `owner: SELF`
→ **resource数量**: wood: XXX, ore: XXX, seed: XXX
→ **船的数量**: ships: XXX
→ **积分points**: points: XXX
表现方式为一个小弹窗

**首次登陆**
显示没有被claim的岛屿，和相应资源量，点击"claim button"。
一个用户只有一个岛。  

#### 船

**点击船**显示, 如果船不是自己的:
→ **owner:** 0xf3... 钱包地址; 
→ **HP**:xxx
→ **Attack**: xxx
→ **Protection**: xxx
→ **speed**: xxx
→ **inventory**: 会有3个格子,显示格子里是什么材料和数量
表现方式为一个小弹窗

**点击船**显示, 如果船是自己的:
→ **owner:** self; 
→ **HP**:xxx
→ **Attack**: xxx
→ **Protection**: xxx
→ **speed**: xxx
→ **inventory**: 会有3个格子,显示格子里是什么材料和数量
→ **inventory button**, 点击跳转船的inventory
表现方式为一个小弹窗


### 2. 地图生成

**grid形状**: 地图的格子组成是等距视角，所有的地图格子都是45度旋转的正方形（菱形）。
**实现**：虽然地图是无限的，但对于给定的玩家只渲染玩家周围的部分, 在玩家移动时更新。

**区块尺寸**：前端渲染时，将地图分成多个区块，每个区块的尺寸为1024x576像素。
使用区块渲染只显示玩家当前视野范围内的区块

**动态加载**：玩家的视野范围内将实时加载地图区块，且玩家移动时将动态加载邻近的新区块。玩家离开的区块从视野中卸载。

#### 岛屿
**岛屿尺寸**：岛屿大小预计为 ~~(100x100)~~ 像素，这个尺寸包括岛屿本身和周围水域的空间。需要与美术团队沟通确定最终尺寸.

**岛屿密度**：基于区块尺寸和岛屿预估尺寸，岛屿数量尽可能多, 并且均匀分布. 

**间距**：岛屿之间需要有足够的空间供船只航行，避免重叠.

### 3. 资源生成
→ :game_die: 3 kinds of resources on each island
→ :game_die: 600 amount for the sum of all the 3 resources
→ :game_die: The min of the each resource is 150. The amount should be randomly generated. 
→ :game_die: After the random generation, the amount of seeds should be floor div by 5 since the later planting function will grow 5 cottons out of 1 seeds. 

```javascript
function distributeResources() {
  const minAmount = 150;
  let wood = minAmount, ore = minAmount, seed = minAmount;
  let remaining = 150; // total is 600, 450 assigned, 150 left to distribute

  while (remaining > 0) {
    let choice = Math.floor(Math.random() * 3);
    if (choice === 0) wood++;
    else if (choice === 1) ore++;
    else seed ++;
    remaining --;
  }

  // floor div by 5 to the amount of seed 
  // since the planting behavior will make 5 cottons out of 1 seeds.
  seed = Math.floor(seed / 5) * 5;

  return { wood, ore, seed };
}

console.log(distributeResources());

```

## 岛屿管理 - 所有的action都可以同时执行

→ after click on botton right **"island" icon button**, different actions icons show up at the bottom. 
→ camera position is set back to the island center. 
<img src="https://hackmd.io/_uploads/SkOgAtdeC.jpg" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">

### 显示以下信息：
```
- 岛的名字，ID
- 岛上待采集资源数量
- 是否occupied，if yes，owner相关
    - owner id
    - 船的数量
    - 已采集资源与数量
    - ongoing action（采集/crafting 以及倒计时）
    
```


### 可以进行以下actions
* **不同的actions 是否能同时执行**:
    * 可以
* **相同的actions 是否能同时执行**: 
    * 除了sailing以外, 其他actions不能同时执行两个相同actions: 如果玩家当前在执行一个mining action, 则玩家不能再同时执行新的mining action, 必须当第一个mining结束后, 才能执行新的mining function

* **资源采集**
    * 用户可以采集 ore/wood或者种树(棉花种子)
    * 点击相应的资源种类，弹窗让用户选择具体资源数量和显示预计时间, 点击弹窗的 “woodcut 按钮”/“mine”按钮, 确认执行
    <img src="https://hackmd.io/_uploads/ryMPtZWgC.jpg" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">
    <img src="https://hackmd.io/_uploads/ryXGFbblR.jpg" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">
    * 能量消耗
        - 砍树 Cut 1 normal tree costs 1 energy token, 3 seconds time duration
        - 挖矿 Mine 1 copper ore costs 1 energy token, 3 seconds time duration
        - 种植
            - :game_die: There are 2 planting grid on each island which means players can grow 2 seeds simultaneously. 
            - :game_die: Plant 1 cotton costs 5 energy token, 3 mins time duration, 5 outputs cotton balls.

* **建造船只**
    * 用户可以用采集的棉花/铜/木头建造船
    * 最左边的按钮是typo? should be "recipe"?选择, default是small ship recipe(mvp只有small ship)
    * 添加修改资源: 玩家点击要加/修改的resource的格子,右边会跳出island inventory, 玩家点击inventory里的resource; 新的resource添加进中间的receipe格子
    * 在玩家放置每一个资源后, update 右上角的ship的三个stats: attack/protection/speed
    * 玩家放满15个资源后, 点击craft button
    * 点击craft出现pop up, popup里会让玩家选择数量/预计消耗的energy token(5个 per ship)/时间(15s per ship), 点击confirm 执行动作

![image](https://hackmd.io/_uploads/SkyCrzqg0.png)




```
→  min amount for each resources is 3. at least 3 ores, 3 woods, 3 plants; but sum needs to reach 15 to craft the small ship. It means players can distribute a total of 6 resources
→  1 ore = 1 attack; 1 wood = 1 protection; 1 plant = 1 speed;
→  crafting 1 small ship cost 5 energy token, 15 seconds time duration
→  For mvp, only small ship is available for craft; other receipes are locked

```
```
class Ship:

    def __init__(self, name="Ship", team="1", attack=3, protection=3, speed=3):
        self.name = name
        self.team = team
        self.hp = 20
        self.attack = attack
        self.protection = protection
        self.speed = speed
        # Points will be distributed by the player.
    
    def distribute_extra_points(self):
        extra_points = 6  # Players can distribute a total of 6 extra points.
        print(f"\nDistributing extra points for {self.name}: (Total extra points: {extra_points})")
        for attr in ['attack', 'protection', 'speed']:
            while True:
                try:
                    points = int(input(f"Enter extra points to add to {attr} (Remaining points: {extra_points}): "))
                    if points <= extra_points:
                        setattr(self, attr, getattr(self, attr) + points)
                        extra_points -= points
                        break
                    else:
                        print("You don't have enough points. Please try again.")
                except ValueError:
                    print("Invalid input. Please enter a number.")
        print(f"Final stats - HP: 20, Attack: {self.attack}, Protection: {self.protection}, Speed: {self.speed}")
image not yet


- 
```
### Island Inventory
→ Players will see a **"inventory" icon** on the bottom menu
→ After clicked on the "inventory" button, there will be a **popup windows** to show all the resources/equipments the players have. 
→ There are 20 grids total which means the inventory can store 20 different things. Same resources/equipment will be accumulated in one grid and counts the amount. 
→ 玩家造出的船会在岛屿边缘的沙滩的相邻海域显示
![image](https://hackmd.io/_uploads/rJpLZ2slR.png)



## Sail & Battle
## Ship Management 船只管理界面
→ After click **"ship icon"** button in the main page, they will be direct to **ship management page**. 

→ 显示的the list of ship stats: ID, HP(total of 20 for small ship), Attack, Protection, Speed

**Roster Buttons**
* 上面有6个tab: all, roster 1, roster 2, roster 3, roster 4, unassigned; 点击roster跳转到该roster
* 一共有4个rosters, 每个roster队列最多拥有4艘船
* "All" 显示所有的船, “Roster 1” 显示roster 1里的船..., “unassigned”显示未被assign的船
<img src="https://hackmd.io/_uploads/rysXK5l7A.png" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">

**Roster1-4内调整船的顺序**
* 玩家可以通过拖拽来arrange船的顺序

**Roster1-4内取消船只button**
* 当船队roster回到island时, 可取消roster内的船
* 玩家可以点击“X” button把此船从roster中去除, 剩余的船往上一移动取代该位置; 被取消的船加入“unassigned”队列

**Roster1-4内添加船只button**
* 当船队roster回到island时, 可以添加船只从unassigned roster中
* 如果该队列的船少于4个, 则没有船的slot会有一个“+”button
<img src="https://hackmd.io/_uploads/rJxLF5eQC.png" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">
* 玩家点击“+”button后跳转到“unassigned”roster, 玩家点击船只, 添加船只进该roster
<img src="https://hackmd.io/_uploads/BJabc5e7C.png" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">



### Ship的inventory 包括 inventory transfer功能
* 同一roster内的船可以互相transfer inventory
* 在岛屿的船可以和island inventory发起transfer
* 当玩家在roster1-4或unassigned roster时, 每一艘船右侧有一个transfer inventory button;

<img src="https://hackmd.io/_uploads/rJxLF5eQC.png" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">


* 玩家点击, 跳转以下界面;
* ship的inventory有3个格子; 相同种类的物资可以叠放;
* ==这一版不会有存不下的问题, 因为只有三种不同的资源;==
<img src="https://hackmd.io/_uploads/r1Evc9emR.png" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">
    * ship transfer 只能与同一roster内的船transfer;
    * 如果ship返回岛屿, roster内的船的inventory也可以和island inventory transfer

### Sailing
* **目的地的选择**
    * 当玩家队列的船>= 1艘船, 可以按下图(左下角)sail button 来执行sail action
    * 当玩家按sail button, 跳转到sailing界面
<img src="https://hackmd.io/_uploads/rJxLF5eQC.png" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">
    * 玩家可以**左击**地图上的坐标(海,船, 岛屿)获取对应信息; 显示信息与前面提及的信息一致
    * 玩家可以**右击**地图上的坐标来选择目的地位置; 右击完成后显示弹窗, 显示信息如下图
    * 玩家点击“Y”后, 船只开始航行, 目的地为adjacent grid, 玩家到达地,不能和岛屿元素重合在一起 ;
    * 玩家点击“N”后, 玩家重新选择目的地坐标
    * 玩家点击“Back” button后, 玩家可以返回船只管理界面
    * 玩家在设置航行目的地后，如果在航行途中想要改变目的地, 可以重新进入船只管理改roster页面, 点击sail选择目的地
<img src="https://hackmd.io/_uploads/r1reYdjx0.png" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">

* **航行速度 与 energy token消耗**
→ :game_die: The energy token will be spent along with time and coordinates it moves.
→ :game_die: The energy token cost = $10\times hrs$. 
→ :game_die: 假设岛屿均匀分布在地图上, 相邻的岛屿航行(A岛到B岛)大概需要20mins(船为5个棉花); 每变化一个棉花数量 ± 2分钟; 航行速度为所有在同一个roster的船的avg




### Ship Battle
* attack 弹窗显示: ==和任何船相邻(在一个相邻的范围内)时, attack popup window 会弹出, 可以被称作“拦截”==。拦截挑战的是整个roster。战斗以roster为单位。
* 玩家点击“**auto-attack**“ button后, 进入战斗页面
* 如果玩家点击“X” button, 可以退出弹窗
<img src="https://hackmd.io/_uploads/B1YSlFje0.png" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">
    * *no trade or steal for mvp*

### Battle Page
https://github.com/serenakeyitan/infinite-seas-ship-battle.git
→ run `shipbattle.py` to test out the combat loop
这个代码的战斗没有implement strategy, 每回合双方默认都执行normal attack
 
* **Brief**
    * 船只能1 roster vs 1 roster; 战斗可以pve也可以pvp; pve和pvp的逻辑是一样,~~哪一方先发起attack, 谁就是P(可以选择每回合策略), 后者为E(自动战斗:每回合只执行normal attack)~~ 双方都是自动战斗（每一回合执行normal attack）；
    * ~~每回合的攻击顺序由骰子和速度variable决定, 轮到该玩家时, 玩家有10秒倒计时可以选择: normal attack 或 swap position 或 pass, 如果10秒内未作出选择, 则执行pass; 当一方玩家的roster中船全部被打败, 结算loot;(具体攻击数值和逻辑见下方)~~
    * 战斗中死亡的船消失, 这个船的invenotry里的items也全部消失, inventory里的items最后更具输赢结算(具体的输赢结算详见下方的winner rewards);


#### ~~关于左下角船的信息显示~~
* ~~我方下面面板显示轮到发起攻击的船的信息，如果有延迟, 可以设置为默认为第一个船~~
* ~~下面的面板显示HP血量, attack, protection, speed~~

#### ~~关于右下角battle button与界面~~
* ~~当玩家click on “battle” button时, 敌方下面的面板显示的船的信息的逻辑和我方的船一样, 有一点和我方不一样的是如果鼠标hover在对方的某一个船上, 优先显示鼠标hover的船的数值.~~

#### ~~关于右下角inventory button与界面~~
* ~~当玩家click on “Inventory” button时, inventory会显示我方所有船的inventory~~



#### Combat Phases 数值与逻辑
→ **Initiation 决定战斗顺序**: Each round begins with the **calculation of turn order**, influenced by each ship's speed attribute and potentially modified by speed abilities.
```python=
# random int from 1 to 8 + speed val
def generate_turn_order(ships):
    turn_order = []
    for ship in ships:
        if ship.hp > 0:  # Only consider ships that are still active
            initiative = random.randint(1, 8) + ship.speed
            turn_order.append((ship, initiative))
    # Sort ships by their initiative score, highest first
    turn_order.sort(key=lambda x: x[1], reverse=True)
    return [ship[0] for ship in turn_order]

```
→ **Action Phase 玩家发起攻击 - 暴击与miss**: Players issue commands by clicking "**normal attack**" button for their ships. Options include **attacking** or strategic **positioning** or **"passing"**.
```python=
# attack
        critical_hit_chance = 0.2  # 20% chance for a critical hit
        critical_miss_chance = 0.35  # 35% chance for a critical miss

# swap position
# pass
```

→ **Resolution 对方玩家承受多少攻击力与闪避机率**: The outcomes of all actions are calculated, including damage dealt and received, effects of special abilities(dodge).
```python=
        # Damage calculation with base formula
        # Damage calc with opp. protection
        if self.attack < opponent.protection:
            damage = max(2, self.attack - (opponent.protection - self.attack) * 0.3)
        else:
            damage = self.attack - opponent.protection * 0.8

        damage = max(0, damage)  # Ensure damage is not negative
```
```python=
        # Dodge check: protection val matters
        dodge_chance = min(60, ((opponent.protection - self.attack) * 8 + 15)) if opponent.protection >= self.attack else 0
        if random.randint(1, 100) <= dodge_chance:
            print(f"{opponent.name} dodged the attack from {self.name}!")
            return
```
→ **Condition Checks 每次action结束后 check conditions**: After actions resolve, the game checks for conditions such as the sinking of ships, or victory conditions being met.
→ **Round Conclusion 每回合游戏输赢 condiion check**: The round ends, and if no victory condition is met, a new round begins with updated game state information.

#### 玩家点击auto attack按钮后，直接弹出自动战斗结果，进入Winner Rewards 赢家战利品计算页面



#### Winner Rewards 赢家战利品计算
* Winner can collect 80% of the resources in the opponent inventory, and 80% of the resources the opponent spent to craft all the ships in the roster.
* When the winning condition met, the either "Victory window" or "Defeat window" will popup. 如下图.
* Victory will have the choice to "Take all" the loot or "cancel"
    * **take all**: 游戏结束后, 点击take all, loot自动储藏到该roster position last的船; 如果对方玩家胜利, 默认选择take all. 
        * Each ship has its own inventory of 3; ship的inventory有3个格子; 相同种类的物资可以叠放; mvp没有存不下的问题. 
    * **cancel**: 玩家点击leave it, 放弃所有loot
<img src="https://hackmd.io/_uploads/HymgKTFzR.png" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">


* Defeat will have the choice to "Back to island" or "not"
    * 积分points的计算是按照打败多少船，如果打败了2艘船即使输了也可以拿积分
<img src="https://hackmd.io/_uploads/r137YpKfR.png" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">





### Combat Targets - PVE & PVP
combat targets are pve ships that are randomly generated

#### Level 1 ship rosters
* 4 ships in a roster and each ship is composed with 8 resources
* base resource: (2,2,2), rest of 2 resources randomly distributed in woods, ores, and cottons. 
* Points 积分: 2/ship
* Loot: level 1 ship rosters `Inventory + 铸造船的资源` floordiv by 1.25
#### Level 2 ship rosters
* 4 ships in a roster and each ship is composed with 12 resources
* base resource: (3,3,3), rest of 3 resources randomly distributed in woods, ores, and cottons.
* Points 积分: 3/ship
* Loot: level 1 ship rosters `Inventory + 铸造船的资源` floordiv by 1.25
#### Level 3 ship rosters
* 4 ships in a roster and each ship is composed with 16 resources
* base resource: (3,3,3), rest of 7 resources randomly distributed in woods, ores, and cottons.
* Points 积分: 6/ship
* Loot: level 1 ship rosters `Inventory + 铸造船的资源` floordiv by 1.25

#### PVP ship rosters
* Points 积分：8/ship
* pvp ship rosters `Inventory + 铸造船的资源` floordiv by 1.25




## Leaderboard
把“ranking”换成leaderboard
- <img src="https://hackmd.io/_uploads/SkOgAtdeC.jpg" width="600" alt="ba07f133ae659003c92dabcb5f1b87e5-2">
按钮为最左边那个钻石按钮, 跳出leader board

## Quests
- [ ] create wallet
- [ ] claim island
- [ ] cut 5 woods
- [ ] mine 5 ores
- [ ] plant 5 cottons
- [ ] craft 1 ship
- [ ] craft 4 ships
- [ ] Battle, and beat 1 pve ship roster


## Admin Function
generate island function;
generate pve ships functiom; add ships to the island randomly for players to challenge (PVE)
claim energy token function;
claim sui token function;


# MISC (don't read)


玩家在岛上收集资源 (消耗energy token), 然后造船(消耗energy token) 然后battle(battle的船有地图会自动生成pve船和玩家的船) 赢家拿走 败者的造船成本用的造船原材料的80%和打败船对应的积分; 做一个排行榜, 比谁积分高 (during campaign)

岛上现在3种资源 木, ore, 棉花: 对应 woodcutting, mining, planting.

造船的base是15个资源: 但必须包括 3个木, 3个ore, 3个棉花; 剩下的6个资源 可以是木, ore, 棉花 在craft的时候自由放进去; 每个资源对应一种属性: 木是防御力, ore是攻击力, 棉花是速度(船帆);

游戏里的battle由一些formula组成都在上面的code里, 包括衍生出来的 Crtical hit/miss, dodge 什么的 为了平衡这三种属性和资源消耗


#### ？？
船在地图上的显示
加上HP条和钱包地址 TODO
可以在地图上看到HP条;

我方的船
→ 做一个小旗子
敌方的船
→ 没有小旗子 美术TODO

岛屿和船在地图上的显示
加上钱包地址
可以在地图上看到钱包地址

我方的岛
→ 做一个小旗子
敌方的岛(以claim)
→ 没有小旗子 美术TODO
敌方的岛(未claim)
→ 岛上只有绿色草坪,没有建筑物/资源 美术TODO






### Claim Energy Test Token


### Claim Island
→ After players claimed both tokens, they can **select one island** on the map to claim island owership. 
→ :construction: Currently, to claim the ownership of an island does not require players to have a stake behind it for testing purpose. 
→ :construction: Islands are unattackable. MVP focuses on PVP between ships.
一个玩家只能拥有一个island

### 可claim的island信息
在玩家还没有岛屿的状态下,左击鼠标点击island时, 会显示以下5个信息: 
→ **owner**: none
→ **resource数量**: wood, ore, seed
→ **island是否已被claim的状态**: 如果可以被claim, 则有一个claim button; 玩家点击claim button获得岛屿
→ **船的数量**
→ **积分points**






### 船的航行速度
假设岛屿均匀分布在地图上, 相邻的岛屿航行(A岛到B岛)大概需要20mins(船为5个棉花); 每变化一个棉花数量 +- 2分钟;
速度为所有在同一个roster的船的avg. 




## Island Management

==所有的action都可以同时执行==
### Mining - simultaneous action
→ Players can click on the bottom right **"island" button** on the main page to manage the resources on island. 
→ Players will see a **"mining" icon** on the bottom menu.
→ After clicked on the "mining" button, there will be a **popup windows** to let players **select the type of ore** they want to mine.
→ ==After players click on the ore, there will be another popup windows that let players select the amount of ores they want to mine, the estimate time duration, and also the estimated energy cost.== **美术还没做, TODO**
→ ==The players can click on the **"Mine" button** on the page to confirm txn==
→ The mined ore will be auto stored in the island inventory

→ :game_die: 
→ :construction: For mvp, only copper ore is available for mine; all other types of ores are locked. ===美术要把TIN那个去掉==


### Woodcutting - simultaneous action
→ Similiar step as mining
→ Players will see a **"woodcutting" icon** on the bottom menu.
→ After clicked on the "woodcutting" button, there will be a **popup windows** to let players **select the type of tree** they want to cut.
→ ==After players click on the tree, there will be another popup windows that let players select the amount of tree they want to cut, the estimate time duration, and also the estimated energy cost.==
→ ==The players can click on the **"woodcutting" button** on the page to confirm txn==
→ The cutted trees will be stored in the inventory

→ :game_die: Cut 1 normal tree costs 1 energy token, 3 seconds time duration
→ :construction: For mvp, only normal tree is available for cut; all other types of trees are locked.


### Planting - simultaneous action
→ Similiar step as mining
→ Players will see a **"planting" icon** on the bottom menu
→ After clicked on the "planting" button, there will be a **popup windows** to let players **select the type of seeds** they want to plant.
→ After players click on the seed, there will be another popup windows that let players select the amount of seeds they want to plant, the estimate time duration, and also the estimated energy cost.
→ Players can click on the **"plant" button** on the page to confirm txn
→ The produce will be stored in the inventory

 
→ :construction: For mvp, only cotton seed is available for plant; all other types of seeds are locked. 

==*image not yet*==

### Crafting - simultaneous action
→ Similiar step as mining
→ Players will see a **"crafting" icon** on the bottom menu.
→ After clicked on the "crafting" button, there will be a **popup windows** to let players **select which receipe** they want to follow. 
→ If they select the **"small ship receipe"** *(only receipe available now)*, they can **increase the required amount** above 3 to max of available points to distribute to the receipe. *(see explaination below)*
→ As players modify the receipt, they are able to see the **ship stats** change. *(see below)*
→ After players click on the receipe, there will be another popup windows that let players select the amount of items they want to craft, the estimate time duration, and also the estimated energy cost.
→ Players can click on the **"craft" button** on the page to confirm txn
→ The produce will be stored in the inventory

→ :game_die: min amount for each resources is 3. at least 3 ores, 3 woods, 3 plants; but sum needs to reach 15 to craft the small ship. It means players can distribute a total of 6 resources
→ :game_die: **1 ore = 1 attack; 1 wood = 1 protection; 1 plant = 1 speed;**
→ :game_die: crafting 1 small ship cost 5 energy token, 15 seconds time duration
→ :construction: For mvp, only small ship is available for craft; other receipes are locked

``` python
class Ship:

    def __init__(self, name="Ship", team="1", attack=3, protection=3, speed=3):
        self.name = name
        self.team = team
        self.hp = 20
        self.attack = attack
        self.protection = protection
        self.speed = speed
        # Points will be distributed by the player.
    
    def distribute_extra_points(self):
        extra_points = 6  # Players can distribute a total of 6 extra points.
        print(f"\nDistributing extra points for {self.name}: (Total extra points: {extra_points})")
        for attr in ['attack', 'protection', 'speed']:
            while True:
                try:
                    points = int(input(f"Enter extra points to add to {attr} (Remaining points: {extra_points}): "))
                    if points <= extra_points:
                        setattr(self, attr, getattr(self, attr) + points)
                        extra_points -= points
                        break
                    else:
                        print("You don't have enough points. Please try again.")
                except ValueError:
                    print("Invalid input. Please enter a number.")
        print(f"Final stats - HP: 20, Attack: {self.attack}, Protection: {self.protection}, Speed: {self.speed}")
```








